【.com原稿】不知不觉,一年一度的春节抢票已经开始了。想抢票快速回家?作为程序员,你必须知道这些技术手段。为了让大家能够更加快捷方便的抢火车票,各种各样的抢票软件应运而生,而这些软件大多都是付费抢票机制。作为程序员,如何用技术手段抢到回家的车票?我们来看看用Python写的抢票脚本。教你用Python抢票回家过年环境介绍windows8.1python3.6.1firefox插件geckodriver.exe操作步骤从selenium.webdriver.support.selectimportSelect#Control下拉导入所需模块boxmodulefromselenium.webdriver.common.byimportBy#Findelementmodulefromselenium.webdriver.support.uiimportWebDriverWait#"显示等待"modulefromselenium.webdriver.supportimportexpected_conditionsasEC#Waitingforconditionalmodule登录模块首先需要选择使用的浏览器,以firefox为这里有一个例子,下载:geckodriver.exe。下载地址:https://github.com/mozilla/geckodriver/releases提到的stations.txt可以直接看到这个:站信息:https://kyfw.12306.cn/otn/resources/js/framework/station_name。js?station_version=1.9042把geckodriver.exe和python.exe放在同级目录下就行了(如果报错,在firefox.exe同级目录下放一个文件,并添加环境变量)#可以用input,就可以了也可以直接放到用户名密码输入框里#可以使用标准输入进行批量操作,这里以个人抢票为例#username=str(input('请输入您的用户名:'))#password=str(input('Pleaseenteryourpassword:'))#这两行可以暂时忽略browser=webdriver.Firefox()#驱动firefox浏览器browser.get("https://kyfw.12306.cn/otn/login/init")#启动浏览器,输入链接browser.find_element_by_id('username').clear()browser.find_element_by_id('username').send_keys('xxxxx')#xxxxx替换更改用户名browser.find_element_by_id('password').send_keys('xxxxx')#xxxxx到密码time.sleep(10)#此时点击验证码,这里设置延迟10秒,可以设置try:browseryourself.find_element_by_id('loginSub').click()#点击登录操作,id为登录按钮#orbrowser.find_element_by_link_text('login').click()#label显示的名称except:browser.find_element_by_class_name('touclick-bgimgtouclick-reloadtouclick-reload-normal').click()#try中验证码输入点错误,这里会刷新一次。不报错直接跳过browser.find_element_by_id('loginSub').click()#点击登录,重新输入验证码后跳转到模块#默认跳转到首页time.sleep(2)#一般没有这里需要设置等待时间,调试使用clickReserve=browser.find_element_by_link_text('ticketreservation').click()#跳转到机票预订页面,这里可以查询机票时间。sleep(2)#出发地点和arrivallocationsetting#这里的值是出发时的位置,BJP是北京的意思,改value值不会加载到页面上,基本不用时间,页面上看不到出发地和目的地#这里的内容是爬取到stations.txt中保存的,每一行代表一个地址,打开文档ctrl+F可以找到值是爬取到stations.txt中的,可以自己查看browser.execute_script(jsf)jst='vara=document.getElementById("toStation");a.value="LZJ"'#终点,同法od同上browser.execute_script(jst)js="document.getElementById('train_date').removeAttribute('readonly')"#时间选择默认只读,通过JS去掉只读属性browser.execute_script(js)#执行JS语句browser.find_element_by_id('train_date').clear()#时间元素默认有提示,需要先清除browser.find_element_by_id('train_date').send_keys('2018-02-01')#根据格式变化输入查询时间search=browser.find_element_by_id('query_ticket').click()#输入信息后点击查询,有成人票和学生票,默认是成人票,如果买的话执行下面语句学生票Just:#browser.find_element_by_id('xxxx').click()#idorclassorotherchoices,[你可以在这里查看](http://blog.51cto.com/12376665/2052278)开始买票这里是点击预约的操作。我只是在这里举一个方法的例子。也可以连续点击直到成功(这样可以避免网站倒计时和实际时间的时间差,但是不知道12306抢票的时候会继续快速访问,没有限制)start_time="ThuJan0408:00:002018"#先设置抢票时间b=time.mktime(time.strptime(start_time,"%a%b%d%H:%M:%S%Y"))print(time.strftime("%a%b%d%H:%M:%S%Y",time.localtime(b)))#这个是为了调试代码,可以忽略,不影响使用=float(b)-time.time()#用你设置的时间减去当前时间的时间戳time.sleep(a)#上一步得到的秒数就是你需要等待的时间ticketgrabtry:#这个本来就是有try的部分就够了。WebDriverWait有相应的等待重复访问机制。默认是每0.5秒测试一次。除了以防万一。WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID,"ticket_2400000Z550L")))#找到需要预定的车次id直到出现,10表示总共等待10秒ticket=browser.find_element_by_xpath('//tr[@id="ticket_2400000Z550L"]/td[13]/a').click()#点击预定按钮except:browser.find_element_by_id('query_ticket').click()WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID,"ticket_2400000Z550L")))ticket=browser.find_element_by_xpath('//tr[@id="ticket_2400000Z550L"]/td[13]/a').click()"""normalPassenger_8数字表示账号的编号,如果是则默认从0开始第一个是normalPassenger_0"""WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID,"normalPassenger_8")))browser.find_element_by_id('normalPassenger_8').click()#id8表示账号下第9位s=Select(browser.find_element_by_id('seatType_1'))s.select_by_value('6')#这里的value值是看下面的各种类型,6代表高级软卧browser.find_element_by_id('submitOrder_id').click()WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID,"qr_submit_id")))browser.find_element_by_link_text('提交订单')browser.find_element_by_id('qr_submit_id').click()#--------------------------------------------------结束#hardseat1#hardsleeper3#softsleeper4#PremiumSoftSleeper6#SecondClassSeatO(大写字母)#FirstClassSeatM#BusinessSeat9需要更换的地方汇总:用户名,密码值起始位置和目的地,检查stations.txt并修改。出发时间。自己选择train的xpath路径,路径不用改,改对应的id即可。检查用户的位置(如果只有一个用户,默认为:normalPassenger_0)。所选座位类别默认为出票类别中最便宜的类别。其余与测试相同,未发现变化。在使用它之前,您可以测试代码。测试是把提交订单的代码注释掉(订单有取消限制,好像一天只能取消3次),测试期间网速正常。有人说用浏览器执行速度会慢。确实,直接识别验证码的脚本,没有界面的会快一些,但实际上用的时间是从预定的开始到结束。相同网络下,代码执行时间大约比手动操作要快。另外,你可以研究时间。之前研究过某宝的时间。秒杀时间比北京时间快几秒。感觉全国各地的时差略有不同。完整脚本示例#python3.6.1#data:2018-01-03#author:LGC247CG"""说明:1.这个脚本主要提供一个实现思路,实现方法有很多,可以优化的地方也很多,并且触发机制也是可以自己设置,代码压缩到最短,方便大家理解2.正常网络情况下,没有设置指定时间的情况下,从点击开始需要1秒左右确认码到下单,所以速度还是慢问题3,由于多人同时查询,与单人查询时间基本相同,希望此方法仅用于技术4、技术交流的情况下,如果验证码可以实现,就可以实现自动抢票:--1>验证码有一定的规则和数量,你可以使用脚本获取所有图片,并添加相应的标签--2>将页面上的文字与标签进行匹配,然后比较图片的相似度计算,点击对应的图片--3>或者训练图片识别模型深度学习,用算法识别"""fromseleniumimportwebdriverfromselenium.webdriver.common.keysimportKeysimporttimefromselenium.webdriver.support.selectimportSelectfromselenium.webdriver.common.byimportByfromselenium.webdriver。support.uiimportWebDriverWaitfromselenium.webdriver.supportimportexpected_conditionsasECbrowser=webdriver.Firefox()browser.get("https://kyfw.12306.cn/otn/login/init")browser.find_element_by_id('用户名').clear()browser.find_element_by_id('用户名').send_keys('xxxxxxx')browser.find_element_by_id('密码').send_keys('xxxxxxx')time.sleep(10)try:browser.find_element_by_id('loginSub').click()except:browser.find_element_by_class_name('touclick-bgimgtouclick-reloadtouclick-reload-normal').click()time.sleep(15)浏览器.find_element_by_id('loginSub').click()#跳转到订票页面time.sleep(2)clickReserve=browser.find_element_by_link_text('订票').click()#出发地和到达地设置WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID,"fromStation")))jsf='vara=document.getElementById("fromStation");a.value="BJP"'browser.execute_script(jsf)jst='vara=document.getElementById("toStation");a.value="LZJ"'browser.execute_script(jst)js="document.getElementById('train_date').removeAttribute('readonly')"browser.execute_script(js)browser.find_element_by_id('train_date').clear()browser.find_element_by_id('train_date').send_keys('2018-02-02')search=browser.find_element_by_id('query_ticket').click()#对于时间,总感觉网站计算的时间和m获得的时间yself的时间差大约是一秒。这个是根据不同的环境测试的。start_time="ThuJan0410:00:002018"#首先设置抢票时间b=time.mktime(time.strptime(start_time,"%a%b%d%H:%M:%S%Y"))print(time.strftime("%a%b%d%H:%M:%S%Y",time.localtime(b)))#这个是为了调试代码,可以忽略,不影响a=float(b)的使用-time.time()#用你设置的时间减去当前时间的时间戳time.sleep(a)#上一步得到的秒数就是等待抢票的时间browser.find_element_by_id('query_ticket').click()#时间到了,点击查询刷新,万一找不到元素try:WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID,"ticket_2400000Z550L")))ticket=browser.find_element_by_xpath('//tr[@id="ticket_2400000Z550L"]/td[13]/a').click()除了:browser.find_element_by_id('query_ticket').click()WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID,"ticket_250000K8880L")))ticket=browser.find_element_by_xpath('//tr[@id="ticket_250000K8880L"]/td[13]/a').点击()"""normalPassenger_8数字表示账号下一个数字,默认从0开始,如果是第一个则为normalPassenger_0"""WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID,"normalPassenger_8")))browser.find_element_by_id('normalPassenger_8').click()s=Select(browser.find_element_by_id('seatType_1'))s.select_by_value('6')browser.find_element_by_id('submitOrder_id').click()WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID,"qr_submit_id")))browser.find_element_by_link_text('提交订单')#browser.find_element_by_id('qr_submit_id').click()作者:LGC247CG简介:从大学开始接触Python,学习过Python爬虫、数据分析、文本处理、图像处理等,有五年应用经验。工作之余,主要用于Linux系统运维脚本[原创稿件,合作站点,转载请注明原作者,出处为.com]
