プログラミングの可能性

電車の乗り換えのソースコード

今回私は電車の乗り換えのソースコードをインターネットから探し、コピーをしたものを少し変えたソースコードを作りました。
参考URL

ソースコード

  1. import datetime
  2. import requests
  3. from bs4 import BeautifulSoup
  4. import urllib3
  5. from urllib3.exceptions import InsecureRequestWarning
  6. urllib3.disable_warnings(InsecureRequestWarning)
  7. from selenium import webdriver
  8. from webdriver_manager.chrome import ChromeDriverManager
  9. from selenium.webdriver.common.by import By
  10. from selenium.webdriver.support.ui import Select
  11. from selenium.common.exceptions import NoSuchElementException
  12. options = webdriver.ChromeOptions()
  13. # ブラウザを表示させる場合、以下をコメントアウト
  14. options.add_argument('--headless')
  15. options.add_argument("-silent")
  16. options.add_argument('log-level=3')
  17. driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
  18. # yahoo
  19. def yahoo_output(route_st_no):#後にY1,Y2とか出て来るのはこれ
  20.     transfer_list = soup.find_all(class_='transfer')
  21.     route_count = int(len(transfer_list) / 2)
  22.     for route_no in range(route_st_no, route_st_no + route_count):
  23.         routename = 'route0' + str(route_no)
  24.         one_route = soup.find(id=routename) # 1ルート分切り出す
  25.         fare = one_route.find(class_='fare').text
  26.         t_start = fare.find(":")
  27.         t_end = fare.find("円")#後でCと出てくるのはこれ
  28.         fare = fare[t_start + 1:t_end]
  29.         fare = fare.replace(',', '')
  30.         time = one_route.find(class_='time').text
  31.         t_start = time.find("発")
  32.         st_time = time[max(0, t_start - 5):t_start]#後でTと出てくるのはここ
  33.         t_end = time.find("着")
  34.         ed_time = time[t_start + 2:t_end]
  35.         t_start = time.find("着")
  36.         t_end = time.find("分")
  37.         time = time[t_start + 1:t_end]
  38.         # 2時間3分→2:03に整形
  39.         time = time.replace('時間', ':')
  40.         time = time.replace('分', '')
  41.         if (time.find(':') == -1):
  42.             time = "0:" + time
  43.         if (time.find(':') == len(time) - 1):
  44.             time = time.replace(':', ':00')
  45.         if (time.find(':') == len(time) - 2):
  46.             time = time.replace(':', ':0')
  47.         print("Y" + str(route_no) + ", " + str(st_time) + " 発, " + str(ed_time) + " 着, T " + str(time) + ", C " + str(
  48.             fare))
  49.         sta = one_route.find_all(class_='station')
  50.         tr = one_route.find_all(class_='transport')
  51.         st_count = -1
  52.         for i in sta:
  53.             st_count = st_count + 1
  54.             st = i.text
  55.             stname = i.find_all("dt")[0].text # 修正(1102)
  56.             # t_start = st.find(']') # 修正(1102)
  57.             # t_end = st.find('\n', t_start + 4) # 修正(1102)
  58.             # stname = st[t_start + 3:t_end] # 修正(1102)
  59.             dep_time = str(st[7:12]) + " 発"
  60.             arr_time = str(st[1:6]) + " 着"
  61.             if (st.find('[dep]') > 0):
  62.                 arr_time = " "
  63.                 dep_time = str(st[1:6]) + " 発"
  64.             if (st.find('[arr]') > 0):
  65.                 dep_time = " "
  66.                 arr_time = str(st[1:6]) + " 着"
  67.                 train = ""
  68.             else:
  69.                 train = tr[st_count].text
  70.                 t_start = train.rfind(']')
  71.                 t_end = train.find('\n', t_start)
  72.                 train = train[t_start + 1:t_end]
  73.             if (st.find('[direct]') == -1):
  74.                 print(" , " + str(arr_time) + ", " + str(dep_time) + ", " + str(stname) + " , " + str(train))
  75. def jorudan_output():
  76.     for b in range(0, len(time_elements)):
  77.         xx = "bR" + str(b + 1)
  78.         one_route = soup.find(id=xx)
  79.         time_use = one_route.find(class_="data_total-time")
  80.         time = time_use.text[4:]
  81.         time = time.replace('時間', ':')
  82.         time = time.replace('分', '')
  83.         if (time.find(':') == -1):
  84.             time = "0:" + time
  85.         if (time.find(':') == len(time) - 1):
  86.             time = time.replace(':', ':00')
  87.         if (time.find(':') == len(time) - 2):
  88.             time = time.replace(':', ':0')
  89.         time_tm = one_route.find(class_="data_tm").text
  90.         time_tm = time_tm.replace('→', '')
  91.         time_tm = time_tm.replace('(', '')
  92.         time_tm = time_tm.replace(')', '')
  93.         time_tm = time_tm.replace('発', ' 発,')
  94.         time_tm = time_tm.replace('着', ' 着')
  95.         time_tm = time_tm.replace(' ', ' ')
  96.         time_tm = time_tm.replace('△', '')
  97.         # 夜行だと日付が出るので削除
  98.         d = time_tm.find("/")
  99.         if (d > -1):
  100.             time_tm = time_tm[:d - 2] + time_tm[d + 4:]
  101.         d = time_tm.find("/")
  102.         if (d > -1):
  103.             time_tm = time_tm[:d - 2] + time_tm[d + 4:]
  104.         time_tm = time_tm.replace(' ', ' ')
  105.         print("J" + str(b + 1) + ", " + time_tm + ", T " + str(time) + ", ", end="")
  106.         cost_element = one_route.find(class_="data_total")
  107.         fare = cost_element.text[3:]
  108.         fare = fare.replace('\n', '')
  109.         fare = fare.replace(',', '')
  110.         index_end = fare.find('円')
  111.         print("C " + str(fare[:index_end]))
  112.         stlist = []
  113.         st_elements = []
  114.         st_elements = one_route.find_all(class_="nm")
  115.         for k in range(0, len(st_elements)):
  116.             stname = st_elements[k].text
  117.             stname = stname.replace('\n', '')
  118.             stlist.append(stname)
  119.         rtime_elements = []
  120.         rtime_elements = one_route.find_all(class_="tm")
  121.         timelist = []
  122.         for k in range(0, len(rtime_elements)):
  123.             rt = rtime_elements[k].text
  124.             if (len(rt) > 1):
  125.                 if (rt.find('乗換') == -1):
  126.                     rt = rt.replace('(', '')
  127.                     rt = rt.replace(')', '')
  128.         sep2 = rt.find('-')
  129.         sep = rt.find(':')
  130.     if (sep2 < sep):
  131.         timelist.append(' ')
  132.     sep = rt.find(':')
  133.     if (sep > 1):
  134.         timelist.append(rt[sep - 2:sep + 3])
  135.     sep = rt.find(':', sep + 1)
  136.     if (sep > 2):
  137.         timelist.append(rt[sep - 2:sep + 3])
  138.     sep = rt.rfind(':')
  139.     if (sep > sep):
  140.         timelist.append(' ')
  141.     rtrain_elements = []
  142.     rtrain_elements = one_route.find_all(class_="rn")
  143.     trainlist = []
  144.     for k in range(0, len(rtrain_elements)):
  145.         rn = rtrain_elements[k].text[1:]
  146.         rn_end = rn.find('\n')
  147.         if (rn_end > 0):
  148.             rn = rn[:rn_end]
  149.         rn = rn.replace('\n', '')
  150.         rn_end = rn.find("行)")
  151.         if (rn_end > 0):
  152.             rn = rn[:rn_end + 2]
  153.         if (len(rn) > -1):
  154.             trainlist.append(rn)
  155.     stlist2 = []
  156.     trainlist2 = []
  157.     timelist2 = []
  158.     for k in range(0, len(stlist) - 1):
  159.         if (stlist[k].find('降車不要') == -1):
  160.             stlist2.append(stlist[k])
  161.             trainlist2.append(trainlist[k])
  162.     if (k > 0):
  163.         timelist2.append(timelist[k * 2 - 1])
  164.     timelist2.append(timelist[k * 2])
  165.     stlist2.append(stlist[k + 1])
  166.     timelist2.append(timelist[len(stlist) * 2 - 3])
  167.     # 表示
  168.     for k in range(0, len(trainlist2)):
  169.         st = " ,"
  170.         if (k == 0):
  171.             st = st + " ,"
  172.         else:
  173.             st = st + " " + str(timelist2[k * 2 - 1]) + " 着,"
  174.         st = st + " " + str(timelist2[k * 2]) + " 発, " + str(stlist2[k]) + " , " + str(trainlist2[k])
  175.         print(st)
  176.     st = " , " + str(timelist2[k * 2 + 1]) + " 着, , " + str(stlist2[k + 1])
  177.     print(st)
  178. def navtime_output():
  179.     summary = soup.find(class_="summary_list time")
  180.     su = summary.text
  181.     routes = su.count('乗換')
  182.     for b in range(0, routes):
  183.         xx = "detail_route_" + str(b)
  184.         one_route = soup.find(id=xx)
  185.         one_route_text = one_route.text
  186.         ttime_start = one_route_text.find('発')
  187.         ttime_end = one_route_text.find('着')
  188.         time_st = one_route_text[ttime_start - 5:ttime_start]
  189.         time_ed = one_route_text[ttime_end - 5:ttime_end]
  190.         ttime_start = one_route_text.find('所要時間')
  191.         ttime_end = one_route_text.find('分')
  192.         ttime = one_route_text[ttime_start + 5:ttime_end]
  193.         ttime = ttime.replace('\t', '')
  194.         ttime = ttime.replace('\n', '')
  195.         ttime = ttime.replace('時間', ':')
  196.         if (ttime.find(':') == -1):
  197.             ttime = "0:" + ttime
  198.         if (ttime.find(':') + 2 == len(ttime)):
  199.             ttime = ttime.replace(':', ':0')
  200.         print("N" + str(b + 1) + ", " + time_st + " 発, " + time_ed + " 着, " + "T " + str(ttime) + ", ", end="")
  201.         xx = "total-fare-text" + str(b + 1)
  202.         cost = one_route.find(id=xx)
  203.         cost_text = cost.text
  204.         cost_text = cost_text.replace(',', '')
  205.         print("C " + str(cost_text))
  206.         tr_elements = []
  207.         tr_elements = one_route.find_all(class_="railroad-area")
  208.         for k in range(0, len(tr_elements)):
  209.             trname = tr_elements[k].text
  210.             trname = trname.replace('\t', '')
  211.             trname = trname.replace('\n', '')
  212.             tr_elements[k] = trname
  213.         st_elements = []
  214.         st_elements = one_route.find_all(class_="section_station_frame")
  215.         for k in range(0, len(st_elements)):
  216.             stname = st_elements[k].text
  217.             stname = stname.replace('発\n', '発X\n')
  218.             stname = stname.replace('着\n', '着X\n')
  219.             if (k == len(st_elements) - 1):
  220.                 platform_elements = one_route.find_all(class_="left platform")
  221.                 if (len(platform_elements) > 0):
  222.                     plat_text = platform_elements[len(platform_elements) - 1].text
  223.                     stname = stname.replace(plat_text, '')
  224.             stname = stname.replace('\t', '')
  225.             stname = stname.replace('混雑予報', 'Z')
  226.             stname = stname.replace('時刻表', '')
  227.             stname = stname.replace('周辺地図', '')
  228.             stname = stname.replace('\n', '')
  229.             stname = stname.replace('出発X', ' , ')
  230.             stname = stname.replace('到着X', ' , ')
  231.             stname = stname.replace('着XZ', '着')
  232.             stname = stname.replace('Z', '')
  233.             stname = stname.replace('着X', ' 着, ')
  234.             stname = stname.replace('発X', ' 発, ')
  235.             if (k < len(st_elements) - 1):
  236.                 trname = tr_elements[k]
  237.                 if (stname.find('乗換不要') == -1):
  238.                     print(" , " + str(stname) + " , " + str(trname))
  239.             else:
  240.                 print(" , " + str(stname))
  241. # main
  242. yahoo_sw = 1
  243. jorudan_sw = 1
  244. navitime_sw = 1
  245. dt_now = datetime.datetime.now()
  246. year = str(dt_now.year)
  247. month = str(dt_now.month)
  248. if (len(month) == 1):
  249.     month = "0" + month
  250. day = str(dt_now.day)
  251. if (len(day) == 1):
  252.     day = "0" + day
  253. start = "横浜"
  254. goal = "番田"
  255. opt = "d"
  256. hh = "17"
  257. mm = "00" # ここまでデフォルト値
  258. while True:
  259.     s = input("出発地点(終了=q) [" + start + "] ")
  260.     if (s == "q"):
  261.         driver.quit()
  262.         break
  263.     if (s == "q"):
  264.         driver.quit()
  265.         break
  266.     if (s != ""):
  267.         start = s
  268.     s = input("到着地点 [" + goal + "] ")
  269.     if (s != ""):
  270.         goal = s
  271.     s = input("日付=" + year + month + day + "(変更はd)、時 [" + hh + "] ")
  272.     if (s == "d"):
  273.         x = input("日[" + day + "] (年月変更はd)")
  274.         if (x == "d"):
  275.             x = input("年[" + year + "]")
  276.             if (x != ""):
  277.                 year = x
  278.                 if (len(year) == 2):
  279.                     year = "20" + year
  280.             x = input("月[" + month + "]")
  281.             if (x != ""):
  282.                 month = x
  283.                 if (len(month) == 1):
  284.                     month = "0" + month
  285.             x = input("日[" + day + "]")
  286.         if (x != ""):
  287.             day = x
  288.             if (len(day) == 1):
  289.                 day = "0" + day
  290.         s = input("時 [" + hh + "] ")
  291.     if (s != ""):
  292.         hh = s
  293.     if (len(hh) == 1):
  294.         hh = "0" + hh
  295.     s = input("分 [" + mm + "] ")
  296.     if (s != ""):
  297.         mm = s
  298.     if (len(mm) == 1):
  299.         mm = "0" + mm
  300.     s = input("出発=>d 到着=>a [" + opt + "] ")
  301.     if (s != ""):
  302.         opt = s
  303.     print(start, goal, year, month, day, hh, mm, opt)
  304.     if (opt == "a"):
  305.         type = "4"
  306.         jtype = "1"
  307.         ntype = "0"
  308.     if (opt == "d"):
  309.         type = "1"
  310.         jtype = "0"
  311.         ntype = "1"
  312.     if (yahoo_sw == 1):
  313.         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[
  314.                                                                                                                                                                                                               0:1] + "&m2=" + mm[
  315.                                                                                                                                                                                                                               1:2] + "&type=" + type + "&ticket=ic" + "&al=1" + "&shin=1" + "&ex=1" + "&hb=1" + "&lb=1" + "&sr=1" + "&s=0" + "&expkind=1" + "&ws=1"
  316.         # BeautifulSoup オブジェクトを作る
  317.         driver.get(URL)
  318.         soup = BeautifulSoup(driver.page_source, "html5lib")
  319.         # yahoo_output(1) # 初めの3件
  320.         try:
  321.             element = driver.find_element_by_link_text('次の3件')
  322.         except NoSuchElementException:
  323.             # print("NoSuchElementException")
  324.             exit
  325.         else:
  326.             URL = element.get_attribute("href")
  327.             driver.get(URL)
  328.             soup = BeautifulSoup(driver.page_source, "html5lib")
  329.             # yahoo_output(4)
  330.     if (jorudan_sw == 1):
  331.         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[
  332.                                                                                                                                                                                    0:1] + "&Dmn2=" + mm[
  333.                                                                                                                                                                                                      1:2] + "&Cway=" + jtype + "&Clate=1&Cfp=1&Czu=2&C7=1&C2=0&C3=0&C1=0&C4=1&C6=1&S=検索"
  334.         driver.get(URL)
  335.         time_elements = []
  336.         time_elements = driver.find_elements_by_class_name("data_total-time")
  337.         if (len(time_elements) == 0):
  338.             # 駅名が複数あって確定できない場合、一番上の選択肢で実行
  339.             print("駅名確定不可")
  340.             element = driver.find_element_by_name("Sok")
  341.             element.click()
  342.             driver.implicitly_wait(3) # seconds
  343.             time_elements = driver.find_elements_by_class_name("data_total-time")
  344.         soup = BeautifulSoup(driver.page_source, "html5lib")
  345.         # jorudan_output()
  346.     if (navitime_sw == 1):
  347.         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="
  348.         driver.get(URL)
  349.         soup = BeautifulSoup(driver.page_source, "html5lib")
  350.         navtime_output()
参考にしたソースコードをただコピー&ペーストしただけではエラーが出たので、少し修正しました。

ソースコードの使い方

:以降の文字の所(出発点など)を自分の最寄り駅や行きたいところ、時間を変えるとその時間で表示されるようになります。

実行結果

11/9 17:00出発の横浜駅から番田駅の実行結果です。
左の写真の(変更はd)というところのように(変更はd)が表示された後にでdを押せば実行後でも場所や時間などを変更することが可能です。
右の写真は表示された乗り換え案内で、一番左のN1やN2はナビタイムで検索した、プラン1やプラン2ということになります。今回はNでしたが、Y(ヤフー)などで表示されることもあります。

まとめ

今回は乗り換え案内のソースコードを探してそれをコピーしたものをベースに修正をして作りましたが、そのままコピーしてペーストしてもエラーが起こることがわかりました。
また、もともとソースコードを作った人はこんなに長いソースコードを作成するのは大変じゃないのかなと感じました。
最後に、今回は乗り換え案内で作成しましたが、調べている段階でビンゴや時計などのソースコードも見つけたのでやってみようかなと思いました。