今天写一下12306火车票查询的爬虫,新手一个,代码方面可能不是那么整洁,望海涵。。。
一。
这个火车票爬虫感觉还是有点难度的,一些小细节需要考虑。
二。
还是先讲一下思路: 获得火车票查询URL----->单击‘单程’------->点击出发输入框,输入城市,选取站点------>目的地输入同上一步------>点击出发日期那个框,选取出发日期.------>点击“查询”按钮------>前面几步用selenuim实现------>创建几个列表,分别存储车次,出发站点,到达站点,出发时间,到达时间,行程耗时。------>创建打印信息函数------>封装函数------>运行程序。。。。。。
三。
先插入所有代码在进行逐步讲解。
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import time import datetime from selenium.webdriver import ActionChains from selenium import webdriver #形参为出发城市,目的地,月份,日。 def train_tickets(scity,ecity,month,day): #打开浏览器 browser = webdriver.Chrome() url = ‘https://kyfw.12306.cn/otn/leftTicket/init‘ browser.get(url) #设置隐形等待 browser.implicitly_wait(15) #选择单程 browser.find_element_by_xpath(‘//label[@for="dc"]‘).click() time.sleep(1) #定位出发城市和目的地城市的输入框 start_city = browser.find_element_by_xpath(‘//input[@id="fromStationText"]‘) end_city = browser.find_element_by_xpath(‘//input[@id="toStationText"]‘) #点击并写入城市。 ActionChains(browser).click(start_city).send_keys(scity).perform() try: list_0 = browser.find_elements_by_xpath(‘//div[@id="panel_cities"]//div/span[1]‘) for vb in list_0: if vb.text == scity: time.sleep(3) vb.click() except: pass time.sleep(3) ActionChains(browser).click(end_city).send_keys(ecity).perform() try: list_01 = browser.find_elements_by_xpath(‘//div[@id="panel_cities"]//div/span[1]‘) for vb2 in list_01: if vb2.text == ecity: time.sleep(3) vb2.click() except: pass time.sleep(3) #选定日期 if month == ‘当月‘: browser.find_element_by_xpath(‘//input[@readonly="readonly"]‘).click() time.sleep(2) qa = browser.find_elements_by_xpath(‘//div[@class="cal-cm"][1]//div[@class="cell"]‘)[int(day)-1] ActionChains(browser).click(qa).perform() time.sleep(3) elif month == ‘下月‘: browser.find_element_by_xpath(‘//input[@readonly="readonly"]‘).click() time.sleep(2) qb = browser.find_elements_by_xpath(‘//div[@class="cal-cm"][2]//div[@class="cell"]‘)[int(day)-1] ActionChains(browser).click(qb).perform() time.sleep(2) #点击查询 browser.find_element_by_xpath(‘//a[@id="query_ticket"]‘).click() time.sleep(3) #车次,出发站,到达站点,出发时间,到达时间,耗时。 che_ci = [] start_c = [] end_c = [] start_t = [] end_t = [] time_2 = [] #获取列车车次,并写入列表。 che_ci_list = browser.find_elements_by_xpath(‘//tbody[@id="queryLeftTable"]//tr[@style="display:none;"]‘) for w in che_ci_list: aa = w.get_attribute(‘datatran‘) che_ci.append(aa) #获取出发站点。 start_c_list = browser.find_elements_by_xpath(‘//strong[@class="start-s"]‘) for w2 in start_c_list: start_c.append(w2.text) #获取目的地站点 end_c_list = browser.find_elements_by_xpath(‘//strong[@class="end-s"]‘) for w3 in end_c_list: end_c.append(w3.text) #获取出发时间 start_t_list = browser.find_elements_by_xpath(‘//strong[@class="start-t"]‘) for w4 in start_t_list: start_t.append(w4.text) #获取到达时间 end_t_list = browser.find_elements_by_xpath(‘//strong[@class="color999"]‘) for w5 in end_t_list: end_t.append(w5.text) #获取耗时 time_2_list = browser.find_elements_by_xpath(‘//div[@class="ls"]‘) for w6 in time_2_list: time_2.append(w6.text) #关闭浏览器。 time.sleep(3) browser.quit() #返回值 return che_ci,start_c,end_c,start_t,end_t,time_2 #qaz = train_tickets(scity=‘北京‘,ecity=‘上海‘,month=‘当月‘,day=‘28‘) #print(qaz) #创建一个打印所有信息的函数。 def print_info(tuple): for aaa,bbb,ccc,ddd,eee,fff in zip(tuple[0],tuple[1],tuple[2],tuple[3],tuple[4],tuple[5]): print(‘车次: %s 出发站点:%s 到达站点:%s 出发时间:%s 到达时间:%s 总耗时:%s ‘ % (aaa,bbb,ccc,ddd,eee,fff)) return True #把函数封装。 def search_train_tickets(): time_1 = datetime.datetime.now() scity = input(‘请输入你的出发城市站点或城市:‘) ecity = input(‘请输入你的目的地城市站点或城市:‘) month = input(‘请输入出发月份(余票只能查询即日起30天的票,输入‘当月’或‘下月’):‘) day = input(‘请输入你几号出发:‘) num_1 = train_tickets(scity=scity,ecity=ecity,month=month,day=day) print_info(num_1) time_2 = datetime.datetime.now() cha = (time_2 - time_1).seconds print(‘\n\n此次运行耗时%s秒。‘ % cha) #运行程序 search_train_tickets()
四。
1.导入模块
import time import datetime from selenium.webdriver import ActionChains from selenium import webdriver
2.打开浏览器,打开网页。
def train_tickets(scity,ecity,month,day): #打开浏览器 browser = webdriver.Chrome() url = ‘https://kyfw.12306.cn/otn/leftTicket/init‘ browser.get(url) #设置隐形等待 browser.implicitly_wait(15)
3.选择行程按钮,并点击。
#选择单程 browser.find_element_by_xpath(‘//label[@for="dc"]‘).click() time.sleep(1)
这里之所以要设置一个等待,是因为我在测试的时候发现,如果操作过快,在最后点击搜索的时候,会卡在搜索状态,一直显示正在搜索。。。。。。
4.定位输入框,写入并选择站点。
#定位出发城市和目的地城市的输入框 start_city = browser.find_element_by_xpath(‘//input[@id="fromStationText"]‘) end_city = browser.find_element_by_xpath(‘//input[@id="toStationText"]‘) #点击并写入城市。 ActionChains(browser).click(start_city).send_keys(scity).perform() try: list_0 = browser.find_elements_by_xpath(‘//div[@id="panel_cities"]//div/span[1]‘) for vb in list_0: if vb.text == scity: time.sleep(3) vb.click() except: pass time.sleep(3) ActionChains(browser).click(end_city).send_keys(ecity).perform() try: list_01 = browser.find_elements_by_xpath(‘//div[@id="panel_cities"]//div/span[1]‘) for vb2 in list_01: if vb2.text == ecity: time.sleep(3) vb2.click() except: pass time.sleep(3)
前两行是用的xpath定位元素。
ActionChains(browser).click(start_city).send_keys(scity).perform()
ActionChains(browser).click(end_city).send_keys(ecity).perform()
这两句是用来对输入框输入文本的语句。
异常包着的是用来选中与出发站点一致的链接,如:我想从北京北站出发,在输入后,会出现很多个站点,所以用次来选中想要出发的站点,并单击。
之所以弄异常处理,是因为我在测试的时候发现明明匹配单击都正确,但是执行后会显示错误,如果你看了本文章,知道出错在哪,希望您能告诉我,谢谢。当然,如果我明白错在哪后也会第一时间修改文章的。
5.选择日期
1 #选定日期 2 if month == ‘当月‘: 3 browser.find_element_by_xpath(‘//input[@readonly="readonly"]‘).click() 4 time.sleep(2) 5 qa = browser.find_elements_by_xpath(‘//div[@class="cal-cm"][1]//div[@class="cell"]‘)[int(day)-1] 6 ActionChains(browser).click(qa).perform() 7 time.sleep(3) 8 elif month == ‘下月‘: 9 browser.find_element_by_xpath(‘//input[@readonly="readonly"]‘).click() 10 time.sleep(2) 11 qb = browser.find_elements_by_xpath(‘//div[@class="cal-cm"][2]//div[@class="cell"]‘)[int(day)-1] 12 ActionChains(browser).click(qb).perform() 13 time.sleep(2) 14 #点击查询
由于火车票只能查询当日起30天的火车票,所以询问‘’当月‘’与“下月”,通过审查元素可以看见,日期分为两块,每块代表的是一个月,所以匹配一个月的,然后将日期转化为索引,获取出发日的那个元素并点击它。
6。点击搜索
1 browser.find_element_by_xpath(‘//a[@id="query_ticket"]‘).click() 2 time.sleep(3)
7.创建需要存储信息的列表,匹配后返回列表。
1 #车次,出发站,到达站点,出发时间,到达时间,耗时。 2 che_ci = [] 3 start_c = [] 4 end_c = [] 5 start_t = [] 6 end_t = [] 7 time_2 = [] 8 #获取列车车次,并写入列表。 9 che_ci_list = browser.find_elements_by_xpath(‘//tbody[@id="queryLeftTable"]//tr[@style="display:none;"]‘) 10 for w in che_ci_list: 11 aa = w.get_attribute(‘datatran‘) 12 che_ci.append(aa) 13 #获取出发站点。 14 start_c_list = browser.find_elements_by_xpath(‘//strong[@class="start-s"]‘) 15 for w2 in start_c_list: 16 start_c.append(w2.text) 17 #获取目的地站点 18 end_c_list = browser.find_elements_by_xpath(‘//strong[@class="end-s"]‘) 19 for w3 in end_c_list: 20 end_c.append(w3.text) 21 #获取出发时间 22 start_t_list = browser.find_elements_by_xpath(‘//strong[@class="start-t"]‘) 23 for w4 in start_t_list: 24 start_t.append(w4.text) 25 #获取到达时间 26 end_t_list = browser.find_elements_by_xpath(‘//strong[@class="color999"]‘) 27 for w5 in end_t_list: 28 end_t.append(w5.text) 29 #获取耗时 30 time_2_list = browser.find_elements_by_xpath(‘//div[@class="ls"]‘) 31 for w6 in time_2_list: 32 time_2.append(w6.text) 33 #关闭浏览器。 34 time.sleep(3) 35 browser.quit() 36 #返回值 37 return che_ci,start_c,end_c,start_t,end_t,time_2
代码中对每一步操作进行了解释,所以在这里就不赘述了。
8.创建是打印信息的函数
1 def print_info(tuple): 2 for aaa,bbb,ccc,ddd,eee,fff in zip(tuple[0],tuple[1],tuple[2],tuple[3],tuple[4],tuple[5]): 3 print(‘车次: %s 出发站点:%s 到达站点:%s 出发时间:%s 到达时间:%s 总耗时:%s ‘ % (aaa,bbb,ccc,ddd,eee,fff)) 4 return True
9.封装函数
1 #把函数封装。 2 def search_train_tickets(): 3 time_1 = datetime.datetime.now() 4 scity = input(‘请输入你的出发城市:‘) 5 ecity = input(‘请输入你的目的地城市:‘) 6 month = input(‘请输入出发月份(余票只能查询即日起30天的票,输入‘当月’或‘下月’):‘) 7 day = input(‘请输入你几号出发:‘) 8 num_1 = train_tickets(scity=scity,ecity=ecity,month=month,day=day) 9 print_info(num_1) 10 time_2 = datetime.datetime.now() 11 cha = (time_2 - time_1).seconds 12 print(‘\n\n此次运行耗时%s秒。‘ % cha)
time_1 = datetime.datetime.now()
time_2 = datetime.datetime.now()
这两句用来获取程序运行开始的时间和运行结束的时间。
10。运行程序
#运行程序 search_train_tickets()
好了,到此就结束了,感谢大家的阅读。
---------------by sniper-huohuo ---------------------
--------------- 知耻而后勇 ----------------------