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 }