- import datetime
- import requests
- from bs4 import BeautifulSoup
- import urllib3
- from urllib3.exceptions import InsecureRequestWarning
- urllib3.disable_warnings(InsecureRequestWarning)
- from selenium import webdriver
- from webdriver_manager.chrome import ChromeDriverManager
- from selenium.webdriver.common.by import By
- from selenium.webdriver.support.ui import Select
- from selenium.common.exceptions import NoSuchElementException
- options = webdriver.ChromeOptions()
- # ブラウザを表示させる場合、以下をコメントアウト
- options.add_argument('--headless')
- options.add_argument("-silent")
- options.add_argument('log-level=3')
- driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
- # yahoo
- def yahoo_output(route_st_no):#後にY1,Y2とか出て来るのはこれ
- transfer_list = soup.find_all(class_='transfer')
- route_count = int(len(transfer_list) / 2)
- for route_no in range(route_st_no, route_st_no + route_count):
- routename = 'route0' + str(route_no)
- one_route = soup.find(id=routename) # 1ルート分切り出す
- fare = one_route.find(class_='fare').text
- t_start = fare.find(":")
- t_end = fare.find("円")#後でCと出てくるのはこれ
- fare = fare[t_start + 1:t_end]
- fare = fare.replace(',', '')
- time = one_route.find(class_='time').text
- t_start = time.find("発")
- st_time = time[max(0, t_start - 5):t_start]#後でTと出てくるのはここ
- t_end = time.find("着")
- ed_time = time[t_start + 2:t_end]
- t_start = time.find("着")
- t_end = time.find("分")
- time = time[t_start + 1:t_end]
- # 2時間3分→2:03に整形
- time = time.replace('時間', ':')
- time = time.replace('分', '')
- if (time.find(':') == -1):
- time = "0:" + time
- if (time.find(':') == len(time) - 1):
- time = time.replace(':', ':00')
- if (time.find(':') == len(time) - 2):
- time = time.replace(':', ':0')
- print("Y" + str(route_no) + ", " + str(st_time) + " 発, " + str(ed_time) + " 着, T " + str(time) + ", C " + str(
- fare))
- sta = one_route.find_all(class_='station')
- tr = one_route.find_all(class_='transport')
- st_count = -1
- for i in sta:
- st_count = st_count + 1
- st = i.text
- stname = i.find_all("dt")[0].text # 修正(1102)
- # t_start = st.find(']') # 修正(1102)
- # t_end = st.find('\n', t_start + 4) # 修正(1102)
- # stname = st[t_start + 3:t_end] # 修正(1102)
- dep_time = str(st[7:12]) + " 発"
- arr_time = str(st[1:6]) + " 着"
- if (st.find('[dep]') > 0):
- arr_time = " "
- dep_time = str(st[1:6]) + " 発"
- if (st.find('[arr]') > 0):
- dep_time = " "
- arr_time = str(st[1:6]) + " 着"
- train = ""
- else:
- train = tr[st_count].text
- t_start = train.rfind(']')
- t_end = train.find('\n', t_start)
- train = train[t_start + 1:t_end]
- if (st.find('[direct]') == -1):
- print(" , " + str(arr_time) + ", " + str(dep_time) + ", " + str(stname) + " , " + str(train))
- def jorudan_output():
- for b in range(0, len(time_elements)):
- xx = "bR" + str(b + 1)
- one_route = soup.find(id=xx)
- time_use = one_route.find(class_="data_total-time")
- time = time_use.text[4:]
- time = time.replace('時間', ':')
- time = time.replace('分', '')
- if (time.find(':') == -1):
- time = "0:" + time
- if (time.find(':') == len(time) - 1):
- time = time.replace(':', ':00')
- if (time.find(':') == len(time) - 2):
- time = time.replace(':', ':0')
- time_tm = one_route.find(class_="data_tm").text
- time_tm = time_tm.replace('→', '')
- time_tm = time_tm.replace('(', '')
- time_tm = time_tm.replace(')', '')
- time_tm = time_tm.replace('発', ' 発,')
- time_tm = time_tm.replace('着', ' 着')
- time_tm = time_tm.replace(' ', ' ')
- time_tm = time_tm.replace('△', '')
- # 夜行だと日付が出るので削除
- d = time_tm.find("/")
- if (d > -1):
- time_tm = time_tm[:d - 2] + time_tm[d + 4:]
- d = time_tm.find("/")
- if (d > -1):
- time_tm = time_tm[:d - 2] + time_tm[d + 4:]
- time_tm = time_tm.replace(' ', ' ')
- print("J" + str(b + 1) + ", " + time_tm + ", T " + str(time) + ", ", end="")
- cost_element = one_route.find(class_="data_total")
- fare = cost_element.text[3:]
- fare = fare.replace('\n', '')
- fare = fare.replace(',', '')
- index_end = fare.find('円')
- print("C " + str(fare[:index_end]))
- stlist = []
- st_elements = []
- st_elements = one_route.find_all(class_="nm")
- for k in range(0, len(st_elements)):
- stname = st_elements[k].text
- stname = stname.replace('\n', '')
- stlist.append(stname)
- rtime_elements = []
- rtime_elements = one_route.find_all(class_="tm")
- timelist = []
- for k in range(0, len(rtime_elements)):
- rt = rtime_elements[k].text
- if (len(rt) > 1):
- if (rt.find('乗換') == -1):
- rt = rt.replace('(', '')
- rt = rt.replace(')', '')
- sep2 = rt.find('-')
- sep = rt.find(':')
- if (sep2 < sep):
- timelist.append(' ')
- sep = rt.find(':')
- if (sep > 1):
- timelist.append(rt[sep - 2:sep + 3])
- sep = rt.find(':', sep + 1)
- if (sep > 2):
- timelist.append(rt[sep - 2:sep + 3])
- sep = rt.rfind(':')
- if (sep > sep):
- timelist.append(' ')
- rtrain_elements = []
- rtrain_elements = one_route.find_all(class_="rn")
- trainlist = []
- for k in range(0, len(rtrain_elements)):
- rn = rtrain_elements[k].text[1:]
- rn_end = rn.find('\n')
- if (rn_end > 0):
- rn = rn[:rn_end]
- rn = rn.replace('\n', '')
- rn_end = rn.find("行)")
- if (rn_end > 0):
- rn = rn[:rn_end + 2]
- if (len(rn) > -1):
- trainlist.append(rn)
- stlist2 = []
- trainlist2 = []
- timelist2 = []
- for k in range(0, len(stlist) - 1):
- if (stlist[k].find('降車不要') == -1):
- stlist2.append(stlist[k])
- trainlist2.append(trainlist[k])
- if (k > 0):
- timelist2.append(timelist[k * 2 - 1])
- timelist2.append(timelist[k * 2])
- stlist2.append(stlist[k + 1])
- timelist2.append(timelist[len(stlist) * 2 - 3])
- # 表示
- for k in range(0, len(trainlist2)):
- st = " ,"
- if (k == 0):
- st = st + " ,"
- else:
- st = st + " " + str(timelist2[k * 2 - 1]) + " 着,"
- st = st + " " + str(timelist2[k * 2]) + " 発, " + str(stlist2[k]) + " , " + str(trainlist2[k])
- print(st)
- st = " , " + str(timelist2[k * 2 + 1]) + " 着, , " + str(stlist2[k + 1])
- print(st)
- def navtime_output():
- summary = soup.find(class_="summary_list time")
- su = summary.text
- routes = su.count('乗換')
- for b in range(0, routes):
- xx = "detail_route_" + str(b)
- one_route = soup.find(id=xx)
- one_route_text = one_route.text
- ttime_start = one_route_text.find('発')
- ttime_end = one_route_text.find('着')
- time_st = one_route_text[ttime_start - 5:ttime_start]
- time_ed = one_route_text[ttime_end - 5:ttime_end]
- ttime_start = one_route_text.find('所要時間')
- ttime_end = one_route_text.find('分')
- ttime = one_route_text[ttime_start + 5:ttime_end]
- ttime = ttime.replace('\t', '')
- ttime = ttime.replace('\n', '')
- ttime = ttime.replace('時間', ':')
- if (ttime.find(':') == -1):
- ttime = "0:" + ttime
- if (ttime.find(':') + 2 == len(ttime)):
- ttime = ttime.replace(':', ':0')
- print("N" + str(b + 1) + ", " + time_st + " 発, " + time_ed + " 着, " + "T " + str(ttime) + ", ", end="")
- xx = "total-fare-text" + str(b + 1)
- cost = one_route.find(id=xx)
- cost_text = cost.text
- cost_text = cost_text.replace(',', '')
- print("C " + str(cost_text))
- tr_elements = []
- tr_elements = one_route.find_all(class_="railroad-area")
- for k in range(0, len(tr_elements)):
- trname = tr_elements[k].text
- trname = trname.replace('\t', '')
- trname = trname.replace('\n', '')
- tr_elements[k] = trname
- st_elements = []
- st_elements = one_route.find_all(class_="section_station_frame")
- for k in range(0, len(st_elements)):
- stname = st_elements[k].text
- stname = stname.replace('発\n', '発X\n')
- stname = stname.replace('着\n', '着X\n')
- if (k == len(st_elements) - 1):
- platform_elements = one_route.find_all(class_="left platform")
- if (len(platform_elements) > 0):
- plat_text = platform_elements[len(platform_elements) - 1].text
- stname = stname.replace(plat_text, '')
- stname = stname.replace('\t', '')
- stname = stname.replace('混雑予報', 'Z')
- stname = stname.replace('時刻表', '')
- stname = stname.replace('周辺地図', '')
- stname = stname.replace('\n', '')
- stname = stname.replace('出発X', ' , ')
- stname = stname.replace('到着X', ' , ')
- stname = stname.replace('着XZ', '着')
- stname = stname.replace('Z', '')
- stname = stname.replace('着X', ' 着, ')
- stname = stname.replace('発X', ' 発, ')
- if (k < len(st_elements) - 1):
- trname = tr_elements[k]
- if (stname.find('乗換不要') == -1):
- print(" , " + str(stname) + " , " + str(trname))
- else:
- print(" , " + str(stname))
- # main
- yahoo_sw = 1
- jorudan_sw = 1
- navitime_sw = 1
- dt_now = datetime.datetime.now()
- year = str(dt_now.year)
- month = str(dt_now.month)
- if (len(month) == 1):
- month = "0" + month
- day = str(dt_now.day)
- if (len(day) == 1):
- day = "0" + day
- start = "横浜"
- goal = "番田"
- opt = "d"
- hh = "17"
- mm = "00" # ここまでデフォルト値
- while True:
- s = input("出発地点(終了=q) [" + start + "] ")
- if (s == "q"):
- driver.quit()
- break
- if (s == "q"):
- driver.quit()
- break
- if (s != ""):
- start = s
- s = input("到着地点 [" + goal + "] ")
- if (s != ""):
- goal = s
- s = input("日付=" + year + month + day + "(変更はd)、時 [" + hh + "] ")
- if (s == "d"):
- x = input("日[" + day + "] (年月変更はd)")
- if (x == "d"):
- x = input("年[" + year + "]")
- if (x != ""):
- year = x
- if (len(year) == 2):
- year = "20" + year
- x = input("月[" + month + "]")
- if (x != ""):
- month = x
- if (len(month) == 1):
- month = "0" + month
- x = input("日[" + day + "]")
- if (x != ""):
- day = x
- if (len(day) == 1):
- day = "0" + day
- s = input("時 [" + hh + "] ")
- if (s != ""):
- hh = s
- if (len(hh) == 1):
- hh = "0" + hh
- s = input("分 [" + mm + "] ")
- if (s != ""):
- mm = s
- if (len(mm) == 1):
- mm = "0" + mm
- s = input("出発=>d 到着=>a [" + opt + "] ")
- if (s != ""):
- opt = s
- print(start, goal, year, month, day, hh, mm, opt)
- if (opt == "a"):
- type = "4"
- jtype = "1"
- ntype = "0"
- if (opt == "d"):
- type = "1"
- jtype = "0"
- ntype = "1"
- if (yahoo_sw == 1):
- URL = "https://transit.yahoo.co.jp/search/result?flatlon=&" + "from=" + start + "&tlatlon=" + "&to=" + goal + "&via=&via=&via=" + "&y=" + year + "&m=" + month + "&d=" + day + "&hh=" + hh + "&m1=" + mm[
- 0:1] + "&m2=" + mm[
- 1:2] + "&type=" + type + "&ticket=ic" + "&al=1" + "&shin=1" + "&ex=1" + "&hb=1" + "&lb=1" + "&sr=1" + "&s=0" + "&expkind=1" + "&ws=1"
- # BeautifulSoup オブジェクトを作る
- driver.get(URL)
- soup = BeautifulSoup(driver.page_source, "html5lib")
- # yahoo_output(1) # 初めの3件
- try:
- element = driver.find_element_by_link_text('次の3件')
- except NoSuchElementException:
- # print("NoSuchElementException")
- exit
- else:
- URL = element.get_attribute("href")
- driver.get(URL)
- soup = BeautifulSoup(driver.page_source, "html5lib")
- # yahoo_output(4)
- if (jorudan_sw == 1):
- URL = "https://www.jorudan.co.jp/norikae/cgi/nori.cgi?eki1=" + start + "&eki2=" + goal + "&eki3=&via_on=1&Dym=" + year + month + "&Ddd=" + day + "&Dhh=" + hh + "&Dmn1=" + mm[
- 0:1] + "&Dmn2=" + mm[
- 1:2] + "&Cway=" + jtype + "&Clate=1&Cfp=1&Czu=2&C7=1&C2=0&C3=0&C1=0&C4=1&C6=1&S=検索"
- driver.get(URL)
- time_elements = []
- time_elements = driver.find_elements_by_class_name("data_total-time")
- if (len(time_elements) == 0):
- # 駅名が複数あって確定できない場合、一番上の選択肢で実行
- print("駅名確定不可")
- element = driver.find_element_by_name("Sok")
- element.click()
- driver.implicitly_wait(3) # seconds
- time_elements = driver.find_elements_by_class_name("data_total-time")
- soup = BeautifulSoup(driver.page_source, "html5lib")
- # jorudan_output()
- if (navitime_sw == 1):
- URL = "https://www.navitime.co.jp/transfer/searchlist?orvStationName=" + start + "&dnvStationName=" + goal + "&thrStationName1=&thrStationCode1=&thrStationName2=&thrStationCode2=&thrStationName3=&thrStationCode3=&month=" + year + "%2F" + month + "&day=" + day + "&hour=" + hh + "&minute=" + mm + "&basis=" + ntype + "&from=view.transfer.searchlist&sort=0&wspeed=83&airplane=1&sprexprs=1&utrexprs=1&othexprs=1&mtrplbus=1&intercitybus=1&ferry=1&accidentRailCode=&accidentRailName=&isrec="
- driver.get(URL)
- soup = BeautifulSoup(driver.page_source, "html5lib")
- navtime_output()
参考にしたソースコードをただコピー&ペーストしただけではエラーが出たので、少し修正しました。
ソースコードの使い方
- start:出発点
- goal:到着点
- hh:時間(時)
- mm:分数(分)
:以降の文字の所(出発点など)を自分の最寄り駅や行きたいところ、時間を変えるとその時間で表示されるようになります。
実行結果
11/9 17:00出発の横浜駅から番田駅の実行結果です。
左の写真の(変更はd)というところのように(変更はd)が表示された後にでdを押せば実行後でも場所や時間などを変更することが可能です。
右の写真は表示された乗り換え案内で、一番左のN1やN2はナビタイムで検索した、プラン1やプラン2ということになります。今回はNでしたが、Y(ヤフー)などで表示されることもあります。
まとめ
今回は乗り換え案内のソースコードを探してそれをコピーしたものをベースに修正をして作りましたが、そのままコピーしてペーストしてもエラーが起こることがわかりました。
また、もともとソースコードを作った人はこんなに長いソースコードを作成するのは大変じゃないのかなと感じました。
最後に、今回は乗り換え案内で作成しましたが、調べている段階でビンゴや時計などのソースコードも見つけたのでやってみようかなと思いました。