今天写一下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 ---------------------
--------------- 知耻而后勇 ----------------------