通过python+splinter,实现在12306网站刷票并自动购票流程(无法自动识别验证码)。
此类程序只是提高了12306网站的 <查询> 刷新频率(默认自动查询的刷新频率为5秒)。对于学习splinter感觉还是不错的,但是想通过装个类似刷票程序成功购票的 还是多花点钱升级升级硬件设备,提高提高网速吧。
程序写的有点乱,随时修改ing。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#!/usr/bin/env python3
# encoding: utf-8
from splinter.browser import Browser
import time
#12306的账号,密码
user_name = 'xxxxxxxxxx' #自行修改
pass_word = 'xxxxxxxxxx'
# 通过splinter,登录12306网站(登录验证码需要手动验证)
b = Browser(driver_name = 'firefox' ) # 设置火狐浏览器
b.visit( 'https://kyfw.12306.cn/otn/leftTicket/init' ) # 打开12306界面
b.find_by_id(u 'login_user' ) # 点击登录按钮
b.fill( 'loginUserDTO.user_name' ,user_name) # 填写账号
b.fill( 'userDTO.password' ,pass_word) # 填写密码
# 手动填写验证码并登录,登录成功后等待自动跳转到购票页面。
'''
跳转页面过程中:
程序可能会报错:[WinError 10053] 您的主机中的软件中止了一个已建立的连接。
原因:未知
解决办法:写一个循环,程序不停的尝试链接跳转页面(总会成功),成功后跳出循环。
'''
while True :
if b.url = = 'https://kyfw.12306.cn/otn/index/initMy12306' : # 判断是否登录成功
try :
b.visit( 'https://kyfw.12306.cn/otn/leftTicket/init' ) # 访问购票页面
except ConnectionAbortedError: #捕捉可能出现的异常,继续访问
b.visit( 'https://kyfw.12306.cn/otn/leftTicket/init' )
if b.url = = 'https://kyfw.12306.cn/otn/leftTicket/init' : # 判断是否跳转购票页面成功
break
# 添加、加载cookies信息,查询余票。(自动添加出发地、目的地、日期,例如:北京-郑州)
b.cookies.add({ '_jc_save_fromDate' : '2018-08-11' }) # 出发日期
b.cookies.add({ '_jc_save_fromStation' :u '%u5317%u4EAC%2CBJP' }) # 出发站信息(北京)
b.cookies.add({ '_jc_save_toDate' : '2018-08-11' }) # 到达日期
b.cookies.add({ '_jc_save_toStation' :u '%u90D1%u5DDE%2CZZF' }) # 目的地信息(郑州)
b. reload () # 重新加载cookies
b.find_by_text(u '查询' ).click() #点击查询
# 添加车次类型
l = [ 'GC-高铁/城际' , 'D-动车' , 'Z-直达' , 'T-特快' , 'K-快速' , '其他' ] #在列表里可以去掉不需要的车次类型
for i in l:
btn = b.find_by_text(i)
btn.click()
# 下拉订票帮手(此步骤可跳过)
b.find_by_id(u 'show_more' ).click()
# 设置坐席
def The_seat():
'''
添加坐席后,网站会自动勾选<自动提交>、<自动查询>功能。
<自动查询> 默认的是5秒刷新一次(慢),所以我们要关闭此选项,提高刷新频率。
'''
seat = [ '二等座' , '软卧' , '硬卧' , '硬座' , '无座' ] #设置一个坐席列表
b.find_by_xpath( '/html/body/div[6]/div[5]/div[2]/div[7]/div[2]/span/a' ).click() #打开坐席选择的菜单窗口
for i in seat:
b.find_by_name(i).click() #添加坐席
b.find_by_xpath( '/html/body/div[11]/div[1]/a' ).click() #关闭弹窗
b.find_by_text(u '开启自动查询' ).click() # 点击关闭<自动查询>选项(慢)。关闭自动查询功能后,自动提交功能也会关闭。
# 购票
def Train_ticket_purchase():
The_seat() #设置坐席
b.find_by_id(u 'show_more' ).click() # 关闭订票帮手(此步骤可跳过)
#查询订票
while b.url ! = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc' : #以预订成功跳转页面为判断条件
try :
b.find_by_text(u '查询' ).click() # 点击查询
if b.is_element_present_by_text(u '预订' ) = = True : #判断是否有<预订>
for i in b.find_by_text(u '预订' ): # b.fin_by_text(u'预订'),返回包含<预订>元素的列表,其中有些可以点击‘预订'购票,有些‘预订'显灰色无票状态,无法点击预订购票的。
if i.has_class( 'btn72' ): #筛选<预订>元素,区分可以点击预订的和不可以点击的(可以点击<预订>的元素,都包含属性class('btn72'))
i.click() #点击预订购票
if b.is_element_present_by_xpath( '//*[@id="content_defaultwarningAlert_hearder"]' ) = = True : #可能会弹窗提示:当前时间不可预订
b.find_by_xpath( '//*[@id="gb_closeDefaultWarningWindowDialog_id"]' ).click() # 关闭提示弹窗
print ( '当前时间不可预订,请关闭程序稍后再运行。' )
break
if b.is_element_present_by_xpath( '//*[@id="content_defaultwarningAlert_title"]' ) = = True : #可能会弹窗提示:您选择的列车距开车时间很近了,请确保有足够的时间抵达车站,并办理换取纸质车票、安全检查、实名制验证及检票等手续,以免耽误您的旅行。
b.find_by_xpath( '//*[@id="qd_closeDefaultWarningWindowDialog_id"]' ).click() #关闭弹窗(注意:关闭弹窗,但是仍然会购票)
b.find_by_text(u 'xxx' )[ 1 ].click() #自行添加乘车人名字(注意:登录账号本人的名字元素可能会有两个(一个账号,一个乘车人),注意区分开)
b.find_by_text(u '提交订单' ).click()
#确认订单(不知道为什么 b.find_by_xpath()方法不行。。。。)
b.find_by_css( 'html body#body_id.dhtmlx_winviewport.dhtmlx_skin_dhx_terrace div.dhtmlx_window_active div.dhtmlx_wins_body_outer div.dhtmlx_wins_body_inner.dhtmlx_wins_no_header div div#checkticketinfo_id div#content_checkticketinfo_id.up-box.w664 div.up-box-bd.ticket-check div#confirmDiv.lay-btn a#qr_submit_id.btn92s' ).click()
print ( '预订成功,退出程序' )
break
else :
print ( '暂时没票,继续查询中...' )
else :
print ( '暂时没票,继续查询中...' )
except :
print ( '不可预订,请稍后再次运行程序...' )
break
if __name__ = = '__main__' :
Train_ticket_purchase()
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/kun_dl/article/details/81031442