Yahoo乗り換え検索を用いて所要時間確認(Pythonバージョン)

スポンサーリンク

IEが動かなくなってもスクレイピングをしたい

私はよくVBAを使ってIEを操作するスクレイピングを好んで使っていたのですが、IEのサポートが終了して使えない機能が出てきました。
(開いている画面を取得して操作できたりなどPythonのBeautifulSoup・SeleniumやGASではできないこともあったので便利だったのですが仕方ないですね…。)

以前にこちらでご紹介した乗り換え検索・所要時間算出ツールもIEをベースに作っていて、画面遷移がないので使えなくはないみたいでしたがアラート表示が出て継続使用に不安が出てきましたので代替のツールを作ってみました。

(ひょっとすると他の乗り換え検索もですが、)Yahooの乗り換え検索は駅・バス停間の所要時間だけでなく、住所を入力すれば住所地からの徒歩の時間も算出してくれるので、おおよその所要時間を把握するのにとても便利です。

今回はPythonのBeautifulSoupを使用して出発地・到着地間の所要時間を算出するコードを書いてみました。

モジュールのインストール

今回はBeautifulSoupとopenpyxlを使用するので、あらかじめ以下のモジュールをインストールしておきます。

rem コマンドプロンプト
pip install beautifulsoup4
pip install openpyxl

スポンサーリンク

用意する条件読み込み用・出力用のExcelファイル

検索条件を入力したり、取得した情報を書き出すためにExcelのファイルを使用します。
書式は以下のようなものを準備していて、A~L列(背景色なし)に所要時間を調べたい条件を入力してPythonのコードを実行するとM~S列(背景色水色)の欄に調べた情報が出力されるものになります。

作成したPythonのコード

# Python
from bs4 import BeautifulSoup

import os
import datetime
from enum import IntEnum

import glob
import openpyxl
import urllib.parse

import requests

t_delta = datetime.timedelta(hours=9)
JST = datetime.timezone(t_delta, 'JST')
now = datetime.datetime.now(JST)
print(now.strftime('%Y%m%d_%H%M%S'))

def getRoute():
    for path in glob.glob(os.getcwd() + r'\py乗り換え検索.xlsx'):
        lwb = openpyxl.load_workbook(filename=path)
        lsh = lwb.worksheets[0]#シート1を選択

        tarRow = 2
        while not lsh.cell(tarRow,1).value is None: #3スタートでセルの値がなくなるまで繰り返す
            print(getUrl(lsh, tarRow))
            response = requests.get(getUrl(lsh, tarRow))
            response.encoding = response.apparent_encoding
            bs = BeautifulSoup(response.text, 'html.parser')
            lsh.cell(tarRow,  int(col.条件入力)).value = bs.select("span.time")[0].text
            lsh.cell(tarRow,  int(col.時間1)).value = bs.select("li.time")[0].text
            lsh.cell(tarRow,  int(col.料金1)).value = bs.select("li.fare")[0].text
            lsh.cell(tarRow,  int(col.時間2)).value = bs.select("li.time")[1].text
            lsh.cell(tarRow,  int(col.料金2)).value = bs.select("li.fare")[1].text
            lsh.cell(tarRow,  int(col.時間3)).value = bs.select("li.time")[2].text
            lsh.cell(tarRow,  int(col.料金3)).value = bs.select("li.fare")[2].text

            tarRow += 1
        lwb.save(path)
        lwb.close

class col(IntEnum):

    出発 = 1
    到着 = 2
    出発到着条件 = 3
    日付 = 4
    時間 = 5
    飛行機 = 6
    新幹線 = 7
    有料特急 = 8
    高速バス = 9
    路線バス = 10
    フェリー = 11
    優先 = 12
    条件入力 = 13
    時間1 = 14
    料金1 = 15
    時間2 = 16
    料金2 = 17
    時間3 = 18
    料金3 = 19

def getUrl(lsh, tarRow):
    
    # return lsh.cell(tarRow,1).value
    出発 = lsh.cell(tarRow,  int(col.出発)).value
    到着 = lsh.cell(tarRow,  int(col.到着)).value

    if lsh.cell(tarRow,  int(col.出発到着条件)).value == "出発":
        検索タイプ = "1"
    elif lsh.cell(tarRow,  int(col.出発到着条件)).value == "到着":
        検索タイプ = "4"
    elif lsh.cell(tarRow,  int(col.出発到着条件)).value == "始発":
        検索タイプ = "3"
    elif lsh.cell(tarRow,  int(col.出発到着条件)).value ==  "終電":
        検索タイプ = "2"
    elif lsh.cell(tarRow,  int(col.出発到着条件)).value ==  "指定なし":
        検索タイプ = "5"
    else:
        検索タイプ = "5"

    if lsh.cell(tarRow,  int(col.日付)) != "" :
        日付 = lsh.cell(tarRow,  int(col.日付)).value
    else:
        日付 = now.strftime('%Y%m%d')
    
    if lsh.cell(tarRow,  int(col.時間)) != "" :
        時間 = lsh.cell(tarRow,  int(col.時間)).value
    else:
        時間 = "9:00"
   
    if lsh.cell(tarRow,  int(col.飛行機)) != "" :
        飛行機 = "1"
    else:
        飛行機 = "0"
   
    if lsh.cell(tarRow,  int(col.新幹線))!= "" :
        新幹線 = "1"
    else:
        新幹線 = "0"
    
    if lsh.cell(tarRow,  int(col.有料特急)) != "" :
        有料特急 = "1"
    else:
        有料特急 = "0"
   
    if lsh.cell(tarRow,  int(col.高速バス)) != "" :
        高速バス = "1"
    else:
        高速バス = "0"
    
    if lsh.cell(tarRow,  int(col.路線バス)) != "" :
        路線バス = "1"
    else:
        路線バス = "0"
   
    if lsh.cell(tarRow,  int(col.フェリー)) != "" :
        フェリー = "1"
    else:
        フェリー = "0"

    if lsh.cell(tarRow,  int(col.優先)) == "到着が早い順":
        検索結果の表示順 = "0"
    elif lsh.cell(tarRow,  int(col.優先)) == "料金が安い順":
        検索結果の表示順 = "1"
    elif lsh.cell(tarRow,  int(col.優先)) == "乗り換え回数順":
        検索結果の表示順 = "2"
    else:
        検索結果の表示順 = "0"

    tarUrl = ("https://transit.yahoo.co.jp/search/result?flatlon=&" + 
    "from=" + urllib.parse.quote(出発) +
    "&tlatlon=" +
    "&to=" + urllib.parse.quote(到着) +
    "&via=&via=&via=" +
    "&y=" + 日付.strftime('%Y') +
    "&m=" + 日付.strftime('%m') +
    "&d=" + 日付.strftime('%d') +
    "&hh=" + 時間.strftime('%H') +
    "&m2=" + 時間.strftime('%M')[1:] +
    "&m1=" + 時間.strftime('%M')[:1] +
    "&type=" + 検索タイプ +
    "&ticket=" + "ic" +
    "&al=" + 飛行機 +
    "&shin=" + 新幹線 +
    "&ex=" + 有料特急 +
    "&hb=" + 高速バス +
    "&lb=" + 路線バス +
    "&sr=" + フェリー +
    "&s=" + 検索結果の表示順 +
    "&expkind=" + "1" + "&ws=" + "3")

    return tarUrl

def sendLineNotify(sendMessage):
    api = "https://notify-api.line.me/api/notify"
    token = "QDSErjbTdCeR5R0mfT7wpKD7HgNQa6MkVyfgLi4vazR"
    headers = {"Authorization" : "Bearer "+ token}

    message = sendMessage
    payload = {"message" :  message}
    post = requests.post(api, headers = headers, params=payload)

def sendGoogleChat(sendMessage):

    webhookUrl = "https://chat.googleapis.com/v1/spaces/AAAAtxHBaG8/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=vwSGCEHFEuWS5ffnp3GXWDH8lPG19VKQQOij1feZyzo"
    requests.post(webhookUrl, json={'text': sendMessage})

getRoute()

こちらのプログラムを実行すると、同じフォルダに格納されているExcelの検索条件を元に、Yahoo乗り換え案内のページを開き、所要時間と交通費を抽出します。
あまり多い件数を試していないので推測ですが1,000件くらいは問題なく出力できると思います。

Yahoo乗り換え案内で入力するパラメータはすべてURLに記載されるGET通信なので、パラメータの記載方法さえわかっていればSeleniumを使わずにBeautifulSoupだけで処理できることがわかりました。

コメント