Python实现12306⾃动抢⽕车票功能
⽬录
⼤家有没有这种感觉,⼀到国庆、春节这种长假,抢⽕车票就⾮常困难?各⼤互联⽹公司都推出抢票服务,只要加钱给服务费就可以增加抢到票的⼏率。有些⽕车票代售⽹点和⼀些加速买票软件,说你只要给100元服务费就可以优先帮忙抢到票。本⽂和你⼀起探索抢票软件背后的原理。
⼀、效果展⽰
很多⼈学习蟒蛇,不知道从何学起。今晚快乐大本营嘉宾是谁
很多⼈学习寻python,掌握了基本语法之后,不知道在哪⾥案例上⼿。
很多已经可能知道案例的⼈,却不怎么去学习更多⾼深的知识。
这三类⼈,我给⼤家提供⼀个好的学习平台,免费获取视频教程,电⼦书,以及课程的源代码
QQ:101677771
欢迎加⼊,⼀起讨论学习
在正式进⼊代码讲解之前,先来看下本⽂的实现效果。
如果不是为了演⽰效果,直接在最后确定阶段加⼀个延时点击确定,应该不到45秒可以锁定⼀张票,只要在30分钟之内付款即可。
⼆、代码详解
本⼩节会详细解锁抢票软件是如何模拟登录⽹站,进⾏⾃动买票的。为了更清晰地给⼤家展⽰,部分代码没有写成函数,直接裸代码运⾏,让需要买票的朋友可以⾃⼰应⽤软件进⾏购票
1 导⼊库
⾸先导⼊本⽂需要加载的库,如果你有些库还没有安装,导致运⾏代码时报错,可以在Anaconda Prompt中⽤pip⽅法安装。
1 2 3 4 5 6 7 8 9 10 11import json
import time
from captcha import*
from selenium import webdriver
from selenium.webdrivermon.by import By
from selenium.webdriver.support import wait
from selenium.webdrivermon.keys import Keys
ptions import NoSuchElementException from selenium.webdrivermon.action_chains import ActionChains from selenium.webdriver.support import expected_conditions as EC #导⼊库
韩娱之韩流全球
2 确定好购票基本信息
导⼊库后,在python代码中填写你购票的基本信息。
1 2 3 4 5 6 7purpose ='ADULT'#购买成⼈票,如果是学⽣票,需调整代码
names =['谢朝阳']              #填写购票⼈姓名
date ='2021-09-21'#填写购票⽇期
start_station ='深圳'#购票出发站
石壕吏原文及翻译end_station ='长沙南'#购票⽬的站
password ='11234567xyz'#登录12306的秘密
username ='xiezhaoyang122700'#登录12306的账号
7 8 9username ='xiezhaoyang122700'#登录12306的账号
trains =['G1004', 'G80', 'G6028', 'G6182', 'G6016']  #你想买的班次#填写基本信息
本⽂预订的是2021年9⽉21⽇从深圳到长沙南的⾼铁票,你可以根据⾃⼰的实际需要进⾏调整。由于有些班次的时间过早或过晚,买了也很不⽅便,所以可以在trains中挑选出你满意的班次进⾏购票。在这⾥需要提醒⼤家,我之前在尝试代码时碰到的坑,那就是时间中如果有个位数要在前⾯填0。⽐如2021年9⽉2⽇,你在填写购票⽇期date时要写成'2021-09-02',否则在运⾏代码时⽇期总是填不进去。
3 登录12306
确定好购票的基本信息后,就可以应⽤python模拟登录12306了,代码如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16options =webdriver.ChromeOptions()
options.add_argument("--disable-blink-features=AutomationControlled")
browser =webdriver.Chrome(options=options)
browser.maximize_window()
login_url ='kyfw.12306/otn/resources/login.html'
#ticket_url = 'kyfw.12306/otn/leftTicket/init'
<(login_url)
time.sleep(0.5)
wait.WebDriverWait(browser, 5).until(EC.element_to_be_clickable((By.CLASS_NAME,'login-hd-account'))).click() input_name =browser.find_element_by_id('J-userName')
input_pd =browser.find_element_by_id('J-password')
input_name.send_keys(username)
input_pd.send_keys(password)
login =browser.find_element_by_id('J-login')
login.click()
#登录12306
整体思路是: 
1.应⽤python模拟调⽤google浏览器;
2.输⼊12306⽹址;
3.等⽹页加载完全后点击账户密码登录;
4.到账号密码的id,把账户密码信息填充进去;
5.到登录id,模拟点击登录按钮。
在这⼀⼩节中要注意两个点。
⼀、要在python安装⽬录中放和google版本匹配的chromedriver,供python调⽤。
⼆、要学会填写账户密码信息的id。
⾸先,在google浏览器中输⼊12306登录⽹址:
接着点击账户密码登录,会出现如下界⾯:
然后点击红框中的三个点,到更多⼯具,点击开发者⼯具,会出现如下界⾯:
点击红框中的箭头,把⿏标移动到账户框上去,就会出现如下界⾯:
右边变灰的框⾥就会出现对应的id,点击账号框,再把⿏标移动到右边变灰的字符上去,点击右键,会出现copy element的选项,复制下来即可。
1<input type="text"class="input"id="J-userName"placeholder="⽤户名/邮箱/⼿机号"aria-label="请输⼊⽤户名/邮箱/⼿机号"title="请输⼊⽤户名/邮箱/⼿机号">
发现了吗?源代码input_name中要填写的browser.find_element_by_id('J-userName')内容,即为id="J-userName"中的信息。
4 模拟滑动滑块
输⼊完⽤户名和密码,点击⽴即登录后,会出现如下滑块验证要求。
运⾏如下代码即可拖动滑块进⾏验证。
1
2browser.implicitly_wait(5)
print('=====开始处理滑动验证码=====')
2 3 4 5 6 7 8 9 10print('=====开始处理滑动验证码=====')
track =[300, 400, 500]
for i in track:
try:
btn =browser.find_element_by_xpath('//*[@id="nc_1__scale_text"]/span')        ActionChains(browser).drag_and_drop_by_offset(btn,i,0).perform()
except:
time.sleep(2)
#拉动滑块验证
其中,browser.implicitly_wait(5)表⽰隐性等待5秒,track中放的是滑块拉动的距离。
5 处理疫情特殊要求
完成滑块验证要求后,会出现如下疫情特殊要求提⽰:
⽤如下代码点击确认即可。
1 2 3 4browser.implicitly_wait(5)
browser.find_element_by_xpath('/html/body/div[5]/div[2]/div[3]/a').click() time.sleep(2)
#疫情特殊要求
browser.find_element_by_xpath和id的区别是,在右键复制时要copy XPath或copy full XPath。
6 点击购票并填写出发地、⽬的地、出发时间
接下来是选择买票,并将出发地、⽬的地、出发时间等信息填写进去。
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 26browser.find_element_by_xpath('//*[@id="J-chepiao"]/a').click()
browser.find_element_by_xpath('//*[@id="megamenu-3"]/div[1]/ul/li[1]/a').click()
browser.find_element_by_xpath('//*[@id="qd_closeDefaultWarningWindowDialog_id"]').click()
#选择买票
def input_info():
print('=====开始买票=====')
from_station =browser.find_element_by_xpath('//*[@id="fromStationText"]')
from_station.send_keys(Keys.ENTER)
from_station.send_keys(Keys.CONTROL, 'a')
from_station.send_keys(start_station, Keys.ENTER)
browser.implicitly_wait(5)
to_station =browser.find_element_by_xpath('//*[@id="toStationText"]')
to_station.send_keys(Keys.ENTER)
赵炳锐
to_station.send_keys(Keys.CONTROL, 'a')
to_station.send_keys(end_station, Keys.ENTER)
browser.implicitly_wait(5)
start_date =browser.find_element_by_xpath('//*[@id="train_date"]')
start_date.send_keys(Keys.ENTER)
start_date.send_keys(Keys.CONTROL, 'a')
start_date.send_keys(Keys.CONTROL, 'x')
start_date.send_keys(date, Keys.ENTER)
browser.implicitly_wait(5)
wait.WebDriverWait(browser, 3).until(EC.element_to_be_clickable((By.ID,'query_ticket'))).click() input_info()
input_info()
#将出发地、⽬的地、出发⽇期填进去
得到结果如下:
这⾥需要注意的是我调⽤了两遍input_info函数,因为12306可能采取了⼀些反爬措施,⼀遍输⼊进去后查不出东西,显⽰为灰⾊。
公众账号7 锁定车票
最后是依次查trains中的车次是否有票,有的话点击购买锁定车票。
1
2 3 4 5trList =browser.find_elements_by_xpath(".//tbody[@id='queryLeftTable']/tr[not(@datatran)]") for tr in trList:
trainNum =tr.find_element_by_class_name("number").text
if trainNum in trains:
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28    if trainNum in trains:
leftTicket =tr.find_element_by_xpath(".//td[4]").text
print('leftTicket', leftTicket)
if leftTicket =='有'or leftTicket.isdigit():
orderBtn =tr.find_element_by_class_name("btn72")
orderBtn.click()
browser.implicitly_wait(5)
passengerLabels =browser.find_elements_by_xpath(".//ul[@id='normal_passenger_id']/li/label")            for passengerLabel in passengerLabels:
name =
if name in names:
passengerLabel.click()
browser.implicitly_wait(20)
# 获取提交按钮
submitBtn =browser.find_element_by_id("submitOrder_id")
submitBtn.click()
browser.implicitly_wait(20)
confirmBtn =browser.find_element_by_id("qr_submit_id")
confirmBtn.click()
time.sleep(2)
browser.implicitly_wait(20)
confirmBtn =browser.find_element_by_id("qr_submit_id")
confirmBtn.click()
军队文职报考条件
break
#依次查trains中的车次是否有票,有的话点击购买
所以,如果你有特别⼼仪的车次,可以在trains中放在最前⾯,依次填写觉得还⾏的车次。⾄此,应⽤python解锁抢票软件背后的原理已讲解完毕,感兴趣的朋友可以⾃⼰跟着本⽂实现⼀遍。
12306不定期会更新买票界⾯,所以过⼀段时间可能之前的代码就要进⾏⼀些调整,需要⾃⼰弄清⾥⾯的原理,才可以以不变应万变。本⽂的代码没有进⾏⾼级的封装,只为⼤家能更清楚地了解每⼀步,
能在抢票⾼峰期买到⾃⼰⼼仪的票。
也写得很基础,没有进⼀步的调优缩短时效,感兴趣的朋友可以⾃⾏研究,如有任何疑问可以跟我沟通。