suumo-search

Perform advanced searches on Suumo.jp
git clone https://git.neuralcrash.com/suumo-search.git
Log | Files | Refs | README

YahooTransitBrowser.java (3843B)


      1 package xyz.kebigon.housesearch.browser.yahoo.transit;
      2 
      3 import java.io.IOException;
      4 import java.util.Collection;
      5 import java.util.HashSet;
      6 
      7 import org.openqa.selenium.By;
      8 import org.openqa.selenium.NoSuchElementException;
      9 import org.openqa.selenium.WebElement;
     10 
     11 import com.fasterxml.jackson.core.JsonParseException;
     12 import com.fasterxml.jackson.databind.JsonMappingException;
     13 
     14 import xyz.kebigon.housesearch.browser.Browser;
     15 import xyz.kebigon.housesearch.domain.Route;
     16 import xyz.kebigon.housesearch.file.RoutesCache;
     17 
     18 public class YahooTransitBrowser extends Browser
     19 {
     20     private final RoutesCache cache;
     21 
     22     public YahooTransitBrowser() throws JsonParseException, JsonMappingException, IOException
     23     {
     24         cache = RoutesCache.load();
     25     }
     26 
     27     @Override
     28     public void close() throws IOException
     29     {
     30         super.close();
     31 
     32         cache.save();
     33     }
     34 
     35     public Collection<Route> search(String from, String to)
     36     {
     37         final String cacheKey = from + "-" + to;
     38 
     39         Collection<Route> routes = cache.get(cacheKey);
     40         if (routes != null)
     41             return routes;
     42 
     43         final String url = YahooTransitSearchURLBuilder.build(from, to);
     44 
     45         navigateTo(url);
     46 
     47         routes = new HashSet<Route>();
     48 
     49         try
     50         {
     51             for (final WebElement element : findElements("//ul[@class='routeList']/li/dl/dd/ul"))
     52                 routes.add(createRoute(from, to, element));
     53 
     54             click("//ul[@id='tabflt']/li[2]/a");
     55 
     56             for (final WebElement element : findElements("//ul[@class='routeList']/li/dl/dd/ul"))
     57                 routes.add(createRoute(from, to, element));
     58 
     59             click("//ul[@id='tabflt']/li[3]/a");
     60 
     61             for (final WebElement element : findElements("//ul[@class='routeList']/li/dl/dd/ul"))
     62                 routes.add(createRoute(from, to, element));
     63         }
     64         catch (final NoSuchElementException e)
     65         {
     66         }
     67 
     68         cache.put(cacheKey, routes);
     69 
     70         return routes;
     71     }
     72 
     73     private static final By TIME_XPATH = By.xpath("./li[@class='time']/span[@class='small']");
     74     private static final By FARE_XPATH = By.xpath("(./li[@class='fare']/div[@class='mark'] | ./li[@class='fare'])[1]");
     75     private static final By TRANSFER_XPATH = By.xpath("(./li[@class='transfer']/div[@class='mark'] | ./li[@class='transfer'])[1]");
     76 
     77     private static Route createRoute(String from, String to, WebElement element)
     78     {
     79         final int time = parseTime(element.findElement(TIME_XPATH).getText());
     80         final int fare = parseFare(element.findElement(FARE_XPATH).getText());
     81         final int transfer = parseTransfert(element.findElement(TRANSFER_XPATH).getText());
     82 
     83         return new Route(from, to, time, fare, transfer);
     84     }
     85 
     86     // 1時間47分 -> 107
     87     private static int parseTime(String timeString)
     88     {
     89         final int hourIndex = timeString.indexOf("時間");
     90         final int minuteIndex = timeString.indexOf('分');
     91 
     92         if (hourIndex != -1)
     93         {
     94             final int hour = Integer.parseInt(timeString.substring(0, hourIndex));
     95             final int minutes = Integer.parseInt(timeString.substring(hourIndex + 2, minuteIndex));
     96 
     97             return hour * 60 + minutes;
     98         }
     99         else
    100             return Integer.parseInt(timeString.substring(0, minuteIndex));
    101     }
    102 
    103     // 1,329円 -> 1329
    104     private static int parseFare(String fareString)
    105     {
    106         return Integer.parseInt(fareString.replace(",", "").replace("円", ""));
    107     }
    108 
    109     // 乗換:2回
    110     // 0回
    111     private static int parseTransfert(String transfertString)
    112     {
    113         if (transfertString.startsWith("乗換:"))
    114             return Integer.parseInt(transfertString.substring(3, transfertString.length() - 1));
    115         else
    116             return Integer.parseInt(transfertString.substring(0, transfertString.length() - 1));
    117     }
    118 }