要过年了,12306监控抢购车票软件已经写好了,亏我Python学得好

目录

一、效果展示

二、代码详解

1 导入库

2 确定好购票基本信息

3 登录12306

4 模拟滑动滑块

5 处理疫情特殊要求

6 点击购票并填写出发地、目的地、出发时间

7 锁定车票

三、实现监控购买

注意

环境

代码

大家有没有这种感觉,一到国庆、春节这种长假,抢火车票就非常困难?各大互联网公司都推出抢票服务,只要加钱给服务费就可以增加抢到票的几率。有些火车票代售网点和一些加速买票软件,说你只要给100元服务费就可以优先帮忙抢到票。

本文和你一起探索抢票软件背后的原理。

私信小编01即可获取大量Python学习资源

一、效果展示

在正式进入代码讲解之前,先来看下本文的实现效果。

如果不是为了演示效果,直接在最后确定阶段加一个延时点击确定,应该不到45秒可以锁定一张票,只要在30分钟之内付款即可。

二、代码详解

本小节会详细解锁抢票软件是如何模拟登录网站,进行自动买票的。为了更清晰地给大家展示,部分代码没有写成函数,直接裸代码运行,让需要买票的朋友可以自己应用软件进行购票。

1 导入库

首先导入本文需要加载的库,如果你有些库还没有安装,导致运行代码时报错,可以在Anaconda Prompt中用pip方法安装。

import json

import time

from captcha import *

from selenium import webdriver

from selenium.webdriver.common.by import By

from selenium.webdriver.support import wait

from selenium.webdriver.common.keys import Keys

from selenium.common.exceptions import NoSuchElementException

from selenium.webdriver.common.action_chains import ActionChains

from selenium.webdriver.support import expected_conditions as EC

#导入库

2 确定好购票基本信息

导入库后,在python代码中填写你购票的基本信息。

purpose = 'ADULT' #购买成人票,如果是学生票,需调整代码

names = ['谢朝阳'] #填写购票人姓名

date = '2021-09-21' #填写购票日期

start_station = '深圳' #购票出发站

end_station = '长沙南' #购票目的站

password = '11234567xyz' #登录12306的秘密

username ='xiezhaoyang122700' #登录12306的账号

trains = ['G1004', 'G80', 'G6028', 'G6182', 'G6016'] #你想买的班次

#填写基本信息

本文预订的是2021年9月21日从深圳到长沙南的高铁票,你可以根据自己的实际需要进行调整。由于有些班次的时间过早或过晚,买了也很不方便,所以可以在trains中挑选出你满意的班次进行购票。在这里需要提醒大家,我之前在尝试代码时碰到的坑,那就是时间中如果有个位数要在前面填0。比如2021年9月2日,你在填写购票日期date时要写成'2021-09-02',否则在运行代码时日期总是填不进去。

3 登录12306

确定好购票的基本信息后,就可以应用python模拟登录12306了,代码如下:

options = webdriver.ChromeOptions()

options.add_argument("--disable-blink-features=AutomationControlled")

browser = webdriver.Chrome(options=options)

browser.maximize_window()

login_url = 'https://kyfw.12306.cn/otn/resources/login.html'

#ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init'

browser.get(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登录网址:

中国铁路12306

接着点击账户密码登录,会出现如下界面:

然后点击红框中的三个点,找到更多工具,点击开发者工具,会出现如下界面:

点击红框中的箭头,把鼠标移动到账户框上去,就会出现如下界面:

右边变灰的框里就会出现对应的id,点击账号框,再把鼠标移动到右边变灰的字符上去,点击右键,会出现copy element的选项,复制下来即可。

<input type="text" class="input" id="J-userName" placeholder="用户名/邮箱/手机号" "height: 44px; line-height: 44px; outline: black 0px;" aria-label="请输入用户名/邮箱/手机号" title="请输入用户名/邮箱/手机号">

发现了吗?源代码input_name中要填写的browser.find_element_by_id('J-userName')内容,即为id="J-userName"中的信息。

4 模拟滑动滑块

输入完用户名和密码,点击立即登录后,会出现如下滑块验证要求。

运行如下代码即可拖动滑块进行验证。

browser.implicitly_wait(5)

print('=====开始处理滑动验证码=====')

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 处理疫情特殊要求

完成滑块验证要求后,会出现如下疫情特殊要求提示:

用如下代码点击确认即可。

browser.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 点击购票并填写出发地、目的地、出发时间

接下来是选择买票,并将出发地、目的地、出发时间等信息填写进去。

browser.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中的车次是否有票,有的话点击购买锁定车票。

trList = 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:

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 = passengerLabel.text

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不定期会更新买票界面,所以过一段时间可能之前的代码就要进行一些调整,需要自己弄清里面的原理,才可以以不变应万变。本文的代码没有进行高级的封装,只为大家能更清楚地了解每一步,能在抢票高峰期买到自己心仪的票。

也写得很基础,没有进一步的调优缩短时效,感兴趣的朋友可以自行研究,如有任何疑问可以跟我沟通。

三、实现监控购买

原代码只能实现购票,我对代码进行了修改,增加了监测和抢票成功推送功能。

需要自行输入12306账号、密码,购买车次、时间、出发站、目的站、server酱key(Server酱·Turbo版 (ftqq.com)去申请)

经测试可成功购票,但有如下问题需要

注意

1.登录测试过多可能会导致滑块验证失败,可自行点击刷新,即可自动执行后续代码(懒得写刷新验证了,只要不是多次运行,一般不会有这个问题)

2.main()中,买票buy那一块,因为我是要抢票,等待时间设置为2,如果是监测,建议设置时间长一点,因为有可能被反爬

3.买票提交按钮可能会有bug,于是我在main中增加了一次选择来确保。但无论如何,进入提交页面你都会收到微信提示,为了保险,建议去看一下是否真的提交了,手动提交也不是不可以。

4.多人买票请在buy()函数下names里填入

5.代码中那么多**code,是我用来标记这段代码是否执行成功,如果没有成功就重复执行,如果code=0,代码没成功,再从头执行,gmcode和code感觉有点重复了,但是,管他呢,能运行就行了, 滑稽.jpg

6.我只是个业余程序猿,代码改的丑陋,我尽量写的通俗易懂了,大佬勿喷。

环境

(食用本代码需要一定的基础知识,新手估计挺难得)python3webdriver以及一些库,我用pycharm,没有的库可以直接导入还有,我觉得最主要的就是webdriver,自己有的话更好,配置的话可能需要很久时间,也挺麻烦的

代码

# -*- coding:utf-8 -*-import jsonimport requestsimport timefrom captcha import *from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import waitfrom selenium.webdriver.common.keys import Keysfrom selenium.common.exceptions import NoSuchElementExceptionfrom selenium.webdriver.common.action_chains import ActionChainsfrom selenium.webdriver.support import expected_conditions as EC# 定义一系列code来确保每一步执行成功再进入下一步global logincode, hkcode, yzcode, xpcode, cpcode, gmcode, code# 初始化def init_program():options = webdriver.ChromeOptions()options.add_argument("--disable-blink-features=AutomationControlled")browser = webdriver.Chrome(options=options)browser.maximize_window()return browser# 登录12306def login(browser):global logincodelogincode = 0password = '' # 登录12306的秘密username = '' # 登录12306的账号login_url = 'https://kyfw.12306.cn/otn/resources/login.html'# ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init'try:browser.get(login_url)time.sleep(0.5)wait.WebDriverWait(browser, 5).until(EC.element_to_be_clickable((By.CLASS_NAME, 'login-hd-code'))).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()logincode = 1except Exception as e:logincode = 0print(e)# 拉动滑块验证def huakuai(browser):global hkcodehkcode = 0try:browser.implicitly_wait(5)print('=====开始处理滑动验证码=====')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()hkcode = 1except:time.sleep(2)except Exception as e:hkcode = 0print(e)# 疫情特殊要求def yiqingyaoqiu(browser):global yzcodeyzcode = 0try:browser.implicitly_wait(5)try:browser.find_element_by_xpath('/html/body/div[4]/div[2]/div[3]/a').click()yzcode = 1except:try:browser.find_element_by_xpath('/html/body/div[2]/div[7]/div[2]/div[3]/a').click()yzcode = 1except:yzcode = 0finally:time.sleep(2)except Exception as e:yzcode = 0print(e)# 进入买票页面def enterbuy(browser):global xpcodexpcode = 0try:browser.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()xpcode = 1except Exception as e:print(e)xpcode = 0# 将出发地、目的地、出发日期填进去def input_info(browser):global cpcodecpcode = 0date = '2022-01-24' # 填写购票日期start_station = '' # 购票出发站,例如南京南end_station = '' # 购票目的站try: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()cpcode = 1except Exception as e:print(e)cpcode = 0# 依次查找trains中的车次是否有票,有的话点击购买def buy(browser):global gmcode, codegmcode = 0code = 0purpose = 'ADULT' # 购买成人票,如果是学生票,需调整代码names = [''] # 填写购票人姓名,需要在你的乘车人管理里有的trains = [] # 你想买的班次,例如'D666', 'G666'browser.implicitly_wait(5)try:trList = browser.find_elements_by_xpath(".//tbody[@id='queryLeftTable']/tr[not(@datatran)]")for tr in trList:trainNum = tr.find_element_by_class_name("number").textif trainNum in trains:leftTicket = tr.find_element_by_xpath(".//td[4]").textprint('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 = passengerLabel.textif 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()code = 1gmcode = 1breakexcept Exception as e:print(e)gmcode = 0def tuisong():api = "https://sctapi.ftqq.com/*****.send" #*****替换成你的微信server酱的key,可以实现购票成功推送,然后你就自己去12306付款title = '购买成功'data = {"text": title}req = requests.post(api, data=data)if __name__ == "__main__":global logincode, yzcode, hkcode, xpcode, cpcode, gmcode, codecode = 0logincode = 0yzcode = 0hkcode = 0xpcode = 0cpcode = 0gmcode = 0browser = init_program()while code == 0:while logincode == 0:login(browser)print('logincode:', logincode)while hkcode == 0:huakuai(browser)print('hkcode:', hkcode)while yzcode == 0:yiqingyaoqiu(browser)print('yzcode:', yzcode)while xpcode == 0:enterbuy(browser)print('xpcode:', xpcode)while cpcode == 0:input_info(browser)input_info(browser)#经测试,一次有可能不成功,我直接两次提交print('cpcode:', cpcode)while gmcode == 0:buy(browser)print('gmcode:', gmcode)print('code:', code)if gmcode == 0:browser.refresh()time.sleep(2)browser.find_element_by_xpath('//*[@id="qd_closeDefaultWarningWindowDialog_id"]').click()input_info(browser)input_info(browser)else:try:print('tijiao')confirmBtn = browser.find_element_by_id("qr_submit_id")browser.implicitly_wait(20)time.sleep(3)confirmBtn.click()except:passif code == 1:tuisong()break

​​

原文地址:https://www.toutiao.com/article/7051761452717474318/

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用OpenCV实现视频去抖 整体步骤: 设置输入输出视频 寻找帧之间的移动:使用opencv的特征检测器,检测前一帧的特征,并使用Lucas-Kanade光流算法在下一帧跟踪这些特征,根据两组点,将前一个坐标系映射到当前坐标系完成刚性(欧几里得)变换,最后使用数组纪录帧之间的运动。 计算帧之间的平
前言 对中文标题使用余弦相似度算法和编辑距离相似度分析进行相似度分析。 准备数据集part1 本次使用的数据集来源于前几年的硕士学位论文,可根据实际需要更换。结构如下所示: 学位论文题名 基于卷积神经网络的人脸识别研究 P2P流媒体视频点播系统设计和研究 校园网安全体系的设计与实现 无线传感器网络中
前言 之前尝试写过一个爬虫,那时对网页请求还不够熟练,用的原理是:爬取整个html文件,然后根据标签页筛选有效信息。 现在看来这种方式无疑是吃力不讨好,因此现在重新写了一个爬取天气的程序。 准备工作 网上能轻松找到的是 101010100 北京这种编号,而查看中国气象局URL,他们使用的是北京545
前言 本文使用Python实现了PCA算法,并使用ORL人脸数据集进行了测试并输出特征脸,简单实现了人脸识别的功能。 1. 准备 ORL人脸数据集共包含40个不同人的400张图像,是在1992年4月至1994年4月期间由英国剑桥的Olivetti研究实验室创建。此数据集包含40个类,每个类含10张图
前言 使用opencv对图像进行操作,要求:(1)定位银行票据的四条边,然后旋正。(2)根据版面分析,分割出小写金额区域。 图像校正 首先是对图像的校正 读取图片 对图片二值化 进行边缘检测 对边缘的进行霍夫曼变换 将变换结果从极坐标空间投影到笛卡尔坐标得到倾斜角 根据倾斜角对主体校正 import
天气预报API 功能 从中国天气网抓取数据返回1-7天的天气数据,包括: 日期 天气 温度 风力 风向 def get_weather(city): 入参: 城市名,type为字符串,如西安、北京,因为数据引用中国气象网,因此只支持中国城市 返回: 1、列表,包括1-7的天气数据,每一天的分别为一个
数据来源:House Prices - Advanced Regression Techniques 参考文献: Comprehensive data exploration with Python 1. 导入数据 import pandas as pd import warnings warnin
同步和异步 同步和异步是指程序的执行方式。在同步执行中,程序会按顺序一个接一个地执行任务,直到当前任务完成。而在异步执行中,程序会在等待当前任务完成的同时,执行其他任务。 同步执行意味着程序会阻塞,等待任务完成,而异步执行则意味着程序不会阻塞,可以同时执行多个任务。 同步和异步的选择取决于你的程序需
实现代码 import time import pydirectinput import keyboard if __name__ == &#39;__main__&#39;: revolve = False while True: time.sleep(0.1) if keyboard.is_pr
本文从多个角度分析了vi编辑器保存退出命令。我们介绍了保存和退出vi编辑器的命令,以及如何撤销更改、移动光标、查找和替换文本等实用命令。希望这些技巧能帮助你更好地使用vi编辑器。
Python中的回车和换行是计算机中文本处理中的两个重要概念,它们在代码编写中扮演着非常重要的角色。本文从多个角度分析了Python中的回车和换行,包括回车和换行的概念、使用方法、使用场景和注意事项。通过本文的介绍,读者可以更好地理解和掌握Python中的回车和换行,从而编写出更加高效和规范的Python代码。
SQL Server启动不了错误1067是一种比较常见的故障,主要原因是数据库服务启动失败、权限不足和数据库文件损坏等。要解决这个问题,我们需要检查服务日志、重启服务器、检查文件权限和恢复数据库文件等。在日常的数据库运维工作中,我们应该时刻关注数据库的运行状况,及时发现并解决问题,以确保数据库的正常运行。
信息模块是一种可重复使用的、可编程的、可扩展的、可维护的、可测试的、可重构的软件组件。信息模块的端接需要从接口设计、数据格式、消息传递、函数调用等方面进行考虑。信息模块的端接需要满足高内聚、低耦合的原则,以保证系统的可扩展性和可维护性。
本文从电脑配置、PyCharm版本、Java版本、配置文件以及程序冲突等多个角度分析了Win10启动不了PyCharm的可能原因,并提供了解决方法。
本文主要从多个角度分析了安装SQL Server 2012时可能出现的错误,并提供了解决方法。
Pycharm是一款非常优秀的Python集成开发环境,它可以让Python开发者更加高效地进行代码编写、调试和测试。在Pycharm中设置解释器非常简单,我们可以通过创建新项目、修改项目解释器、设置全局解释器等多种方式进行设置。
Python中有多种方法可以将字符串转换为整数,包括使用int()函数、try-except语句、正则表达式、map()函数、ord()函数和reduce()函数。在实际应用中,应根据具体情况选择最合适的方法。
本文介绍了导入CSV文件的多种方法,包括使用Excel、Python和R等工具。同时,还介绍了导入CSV文件时需要注意的一些细节和问题。CSV文件是数据处理和分析中不可或缺的一部分,希望本文能够对读者有所帮助。
mongodb是一种新型的数据库,它采用了面向文档的数据模型,具有灵活性、高性能和高可用性等优势。但是,mongodb也存在数据结构混乱、安全性和学习成本高等问题。
当Python运行不了时,我们应该从代码、Python环境、操作系统和硬件设备等多个角度来排查问题,并采取相应的解决措施。