【Python】SeleniumでHeadless Chromeを用いたWebスクレイピング (目的地までの所要時間を調べる)

## 概要
入力された『出発地』から『目的地』までの所要時間をWebスクレイピングにより取得するPythonスクリプトを開発してみた．

## 開発
システム環境: macOS, Python 3.6.5以降

外部ライブラリをインストールする．

```zsh
pip3 install selenium
```

Pythonスクリプトとパッケージ・モジュールを作成する．

```zsh
mkdir ~/RequiredTimeSearcher
touch ~/RequiredTimeSearcher/required_time_searcher.py
mkdir ~/RequiredTimeSearcher/common
touch ~/RequiredTimeSearcher/common/browser_controller.py
```

**モジュール`browser_controller.py`のソースコード**

```python:browser_controller.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from selenium.webdriver import ChromeOptions, Chrome
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

class Transit:
    def __init__(self):
        self.start = input('出発予定地を入力してください: ')
        self.end = input('到着予定地を入力してください: ')
        self.options = ChromeOptions()

        # Chrome起動時のオプションを設定
        self.startOptions()
        self.driver = Chrome(options=self.options)

    # 検索開始の表示するメソッド
    def startMessage(self):
        print('『' + self.start + '』' + 'から' + '『' + self.end + '』' + 'への所要時間を検索中...\n')

    # 処理を早めるためにChrome起動時のオプションを設定
    def startOptions(self):

        # UserAgentをヘッドレスモードに設定
        self.options.add_argument('--headless')
        self.options.add_argument('--disable-gpu')

        # SSLエラーを許容
        self.options.add_argument('--ignore-certificate-errors')

        # シークレットモード指定
        self.options.add_argument('--incognito')

        # 画像を読み込まないよう設定
        self.options.add_argument('--blink-settings=imagesEnabled=false')

    # Chromeを起動するメソッド
    def chromeStart(self):
        url = 'https://transit.yahoo.co.jp/'
        self.driver.get(url)

    # フォームに地名を入力して検索するメソッド
    def transitInput(self):
        self.driver.find_element(By.NAME, 'from').send_keys(self.start)
        self.driver.find_element(By.NAME, 'to').send_keys(self.end)
        self.driver.find_element(By.ID, 'searchModuleSubmit').click()

    # 所要時間を取得するメソッド (XPathで指定)
    def getText(self):

        # 要素の存在確認用の変数宣言 (elementsでなくelementsとする)
        elements = self.driver.find_elements(By.XPATH, '//*[@id="rsltlst"]/li/dl/dd/ul/li[1]/span[2]')

        # 上記要素が存在するか否かで分岐処理
        if elements:
            self.time = self.driver.find_element(By.XPATH, '//*[@id="rsltlst"]/li/dl/dd/ul/li[1]/span[2]').text
            print('所要時間: ' + self.time)
        else:
            print('正しい地名を入力してください')
            exit()

    # Chromeを終了するメソッド
    def chromeShutdown(self):
        self.driver.quit()
```

**実行ファイル`required_time_searcher.py`のソースコード**

```python:required_time_searcher.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from common.browser_controller import Transit

def main():

    # インスタンスの生成
    operation = Transit()

    # メソッドの呼び出し
    operation.startMessage()
    operation.chromeStart()
    operation.transitInput()
    operation.getText()
    operation.chromeShutdown()

if __name__ == '__main__':
    main()
```

#実行

**required_time_searcher.pyを実行**

```bash
$ python ~/RequiredTimeSearcher/required time_searcher.py
出発予定地を入力してください: 浜松町 #出発地を入力
到着予定地を入力してください: 駒込 #目的地を入力
『浜松町』から『駒込』への所要時間を検索中...

所要時間: 25分
```

例として出発地に『浜松町』，目的地に『駒込』を入力してみたところ所要時間25分が得られた．