Hello everyone! Today I'm gona tell you about a common situation in life:
- you need to buy a ticket for a precise date but there are no available (oh crap!)
- you know 95% for sure that some tickets will appear for sale suddenly, you want to get them!
- you have no time and patience to track site from time to time to check for those tickets
- you can write a programm that'll do this for you
- ...
- profit!
The idea is to perform repeatable GET requests for your specific demands
- From city
- To city
- Date
- e.t.c.
..after you find this "bookmarkable GET" all you need is to parse the income HTML for information you need.
So let's go!
Requirements
- Programm must track the site for available tickets and try to find those you need
- It's notify you fast (!) right after it'll find the appropriate ticket
Prerequisites
MyYour favourite text editor or IDE- JSOUP library for HTML parsing
- JavaMail library for sending you an email (optional)
Analyse
First thing you need to do is to find a site, which you're going to track for tickets.
I'd chosen this one because it's in Russia and have a funy name :)
Now find a bookmarkable GET request and get common with it's structure. In my case it was:
Here as you can see, from-city, to-city and date are configurable and easy to change.
Next, analyse the structure of the site and it's HTML layout.
Think about "what I want to track for" and create a model of it:
In this example we have the <table> of available train and tickets for them </table> with static id=schedule_table, so we can parse it and retrieve the information we need to proceed. In the table there are <tr> elements </tr> that represents trains, we can just iterate thru them. In trains there are <td> columns </td> that we can iterate just for their index, because they have static layout.
Let's assume that I want to know when new seat places will appear for sale. See the following algorithm to understand how we can identify this case.
Structure and algorithm:
So in our programm we are saying the following:
If the number of <p> elements is more than 1 that means that new places appear for sale
Ok, lets code this.
Code
What you need is a fast solution, so forget all this stuff about OOP principles, clean code or architecture :)
1. Create a new class with a main method
public class TrainDaemon { public static void main(String[] args) { } }
2. Establish a HTTP connection
URL url = new URL("http://www.tutu.ru:80/poezda/rasp_d.php?nnst1=2010280&nnst2=2004000&date=19.08.2012"); HttpURLConnection uc = (HttpURLConnection)url.openConnection(); uc.connect();
or via proxy
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxyhost", 12345)); URL url = new URL("http://www.tutu.ru:80/poezda/rasp_d.php?nnst1=2010280&nnst2=2004000&date=19.08.2012"); HttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy); uc.connect();
3. White a parsing solution with the help of JSOUP
StringBuffer tmp; try { URL url = new URL("http://www.tutu.ru:80/poezda/rasp_d.php?nnst1=2010280&nnst2=2004000&date="+date); HttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy); uc.connect(); String line = null; tmp = new StringBuffer(); BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream())); while ((line = in.readLine()) != null) { tmp.append(line); } } catch (MalformedURLException e1) { } catch (IOException e) {} Document doc = Jsoup.parse(String.valueOf(tmp)); Elements table = doc.getElementsByAttributeValue("id", "schedule_table"); for (Element el : table) { Elements tbodys = el.getElementsByTag("tbody"); Elements trains = tbodys.get(0).getElementsByTag("tr"); System.out.println(trains.size() + " trains"); for (Element train : trains) { int i = 0; for (Element td : train.getElementsByTag("td")) { if (i == 9) { Elements ps = td.getElementsByTag("p"); System.out.println(ps.size()+" places"); if (ps.size() > 1) return true; // TADA! } i++; } } } return false; // another time...
4. Notify you if hit (if TADA!)
Here is a good tutorial of how to send emails in Java or you can use any other notifier (just console log for example).
5. Put all together in a loop
// PERIOD = 60000 = 1min long currentTime = System.currentTimeMillis() - PERIOD; while (true) { while (System.currentTimeMillis() - currentTime < PERIOD) {} System.out.println(System.currentTimeMillis() + " attempt:"); for (String date : DATES) { System.out.println("date: " + date); String result = checkForDate(date); if (result != null) { System.out.println(result); pw.println(result); pw.flush(); } } System.out.println("attempt end in: " + (System.currentTimeMillis() - currentTime - PERIOD)); currentTime = System.currentTimeMillis(); }
Result
As a result you have very bad, not optimized, but working programm that frees you from routine hand-checking tickets and automaticly notifies you if something you need just appeared.
My console log looks like this
here you can see that it just appeared 2 places for 19.08.2012
so I'm gona finish writing and go buy the tickets :)
P.S.: You can also imrove the programm to automaticly reserve (buy) you tickets after successful hit.
so I'm gona finish writing and go buy the tickets :)
Have a happy codding!
P.S.: You can also imrove the programm to automaticly reserve (buy) you tickets after successful hit.
Этот комментарий был удален администратором блога.
ОтветитьУдалить