Python实现全自动购买火车票!抢票回家过年咯
本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理
这个是实现结果,因为一天只能取消三次,所以最后一步点击确认被我注释了
1.首先实现使用selenium登陆12306

这里实现了使用selenium登陆12306,实现全自动登陆12306链接
2.根据上面实现登陆后,实现购买火车票还需两步
这里只进行了二等座的查询和购票,想要买其他的自己也可以进行修改 1.进行车票的查询 这里面需要注意的是在输入目的地和起始地时需要先click一下文本框browser.find_element_by_id(‘fromStationText’).click() 不然输入的地址无效 还有将日期的只读属性去掉
def search_railway_ticket(fromstation,tostation,train_date):
# 火车票页面查询url
search_url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc'
# 转到查询车次页面
browser.get(search_url)
time.sleep(2)
#输入出发地
WebDriverWait(browser, 1000).until(
EC.presence_of_element_located((By.ID, 'fromStationText'))
)
#先点击一下
browser.find_element_by_id('fromStationText').click()
browser.find_element_by_id('fromStationText').send_keys(fromstation)
browser.find_element_by_id('fromStationText').send_keys(Keys.ENTER)
time.sleep(1)
WebDriverWait(browser, 1000).until(
EC.presence_of_element_located((By.ID, 'toStationText'))
)
#输入目的地
browser.find_element_by_id('toStationText').click()
browser.find_element_by_id('toStationText').send_keys(tostation)
browser.find_element_by_id('toStationText').send_keys(Keys.ENTER)
time.sleep(5)
#将日期的只读属性去掉
js = 'document.getElementById("train_date").removeAttribute("readonly")'
browser.execute_script(js)
#去掉原本的时间
WebDriverWait(browser, 1000).until(
EC.presence_of_element_located((By.ID, 'train_date'))
)
browser.find_element_by_id("train_date").clear()
#输入出发时间
browser.find_element_by_id('train_date').send_keys(train_date)
# 等待查询按钮是否可用
WebDriverWait(browser, 1000).until(
EC.element_to_be_clickable((By.ID, 'query_ticket'))
)
searBtn = browser.find_element_by_id('query_ticket')
searBtn.click()
print('点击按钮')
2.购买火车票 在这个函数中需要注意的是最好把最后一步注释掉 browser.find_element_by_id(‘qr_submit_id’).click() 因为一天只能取消3次订单
def buy_ticket(fromstation,tostation,train_date,train_number,passenger):
#查询火车票
search_railway_ticket(fromstation,tostation,train_date)
time.sleep(5)
#获取每一个车次的信息
tr_list = browser.find_elements_by_xpath('.//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
for tr in tr_list:
#获取车次号
number = tr.find_element_by_class_name('number').text
if number in train_number:
#获取是否还有票
left_ticket = tr.find_element_by_xpath('./td[4]').text
if left_ticket =='有'or left_ticket.isdigit:
print(f'{number}还有票')
#点击预订
orderBtn = tr.find_element_by_class_name('btn72')
orderBtn.click()
time.sleep(5)
#获取12306中乘客的信息
passenger_list = browser.find_elements_by_xpath('//*[@id="normal_passenger_id"]/li')
for li in passenger_list:
name = li.find_element_by_xpath('./label').text
print(name)
#配对12306人名
if name == passenger:
li.find_element_by_tag_name('input').click()
#提交订单
submit = browser.find_element_by_id('submitOrder_id')
submit.click()
WebDriverWait(browser, 1000).until(
EC.element_to_be_clickable((By.ID, 'qr_submit_id'))
)
#一天只能取消3次 所以最好把最后一步注释了
browser.find_element_by_id('qr_submit_id').click()
print('已经提交订单')
break
下面是源代码
测试的时候可以把#click_captcha()这个点击验证码的去掉自己手动点击,这样就不用扣超级鹰的积分(有钱的话当我没说),留下了贫穷的泪水。
from selenium import webdriver
from selenium.webdriver import Actionchains
import time
from PIL import Image
import requests
from hashlib import md5
from selenium.webdriver import ChromeOptions
#验证码识别处理
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf8')
self.password = md5(password).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
return r.json()
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
def login(username,password):
# 填写账号密码
browser.find_element_by_id('J-userName').send_keys(username)
browser.find_element_by_id('J-password').send_keys(password)
# 获取验证码
get_captcha()
# 填写验证码
click_captcha()
#点击登录
time.sleep(4)
browser.find_element_by_id('J-login').click()
time.sleep(4)
#滑动验证码
slider()
print('成功登陆')
time.sleep(5)
def slider():
#滑动验证码
WebDriverWait(browser, 1000).until(
EC.presence_of_element_located((By.XPATH, '//*[@id="nc_1_n1z"]'))
)
span = browser.find_element_by_xpath('//*[@id="nc_1_n1z"]')
# 对div_tag进行滑动操作
action = Actionchains(browser)
# 点击长按指定的标签
action.click_and_hold(span).perform()
action.drag_and_drop_by_offset(span, 400, 0).perform()
def click_captcha():
# 获取验证码需要的为点击位置
chaojiying = Chaojiying_Client('自己的用户名', '密码', '软件id') # 用户中心>>软件ID 生成一个替换 96001
im = open('./captcha.png', 'rb').read() # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
location = chaojiying.PostPic(im, 9004)['pic_str'] # 1902 验证码类型 官方网站>>价格体系 3.4+版 print 后要加()
print(chaojiying.PostPic(im, 9004))
# 将位置进行分割成 [ [ ], [ ], [ ] ]类型
location_list = [i.split(',') for i in location.split('|')]
for l in location_list:
x = l[0]
y = l[1]
Actionchains(browser).move_to_element_with_offset(browser.find_element_by_class_name('login-pwd-code'), int(x),int(y)).click().perform()
time.sleep(0.5)
def get_captcha():
# 获取网页的截图
allscreen = browser.get_screenshot_as_file('allscreen.png')
# 获取captcha
captcha = browser.find_element_by_class_name('login-pwd-code')
# 获取captcha的左上角位置
location = captcha.location
# 获取图片大小
size = captcha.size
# 裁取captcha
rangle = (location['x'],location['y'],(location['x']+size['width']),(location['y']+size['height']))
i = Image.open('./allscreen.png')
captcha_img = './captcha.png'
frame = i.crop(rangle)
frame.save(captcha_img)
def buy_ticket(fromstation,tostation,train_date,train_number,passenger):
#查询火车票
search_railway_ticket(fromstation,tostation,train_date)
time.sleep(5)
tr_list = browser.find_elements_by_xpath('.//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
for tr in tr_list:
number = tr.find_element_by_class_name('number').text
if number in train_number:
left_ticket = tr.find_element_by_xpath('./td[4]').text
if left_ticket =='有'or left_ticket.isdigit:
print(f'{number}还有票')
orderBtn = tr.find_element_by_class_name('btn72')
orderBtn.click()
time.sleep(5)
passenger_list = browser.find_elements_by_xpath('//*[@id="normal_passenger_id"]/li')
for li in passenger_list:
name = li.find_element_by_xpath('./label').text
if name == passenger:
li.find_element_by_tag_name('input').click()
submit = browser.find_element_by_id('submitOrder_id')
submit.click()
WebDriverWait(browser, 1000).until(
EC.element_to_be_clickable((By.ID, 'qr_submit_id'))
)
#一天只能取消3次 所以把最后一步注释了
# browser.find_element_by_id('qr_submit_id').click()
print('已经提交订单')
break
def search_railway_ticket(fromstation,tostation,train_date):
# 火车票页面查询url
search_url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc'
# 转到查询车次页面
browser.get(search_url)
time.sleep(2)
#输入出发地
WebDriverWait(browser, 1000).until(
EC.presence_of_element_located((By.ID, 'fromStationText'))
)
#先点击一下
browser.find_element_by_id('fromStationText').click()
browser.find_element_by_id('fromStationText').send_keys(fromstation)
browser.find_element_by_id('fromStationText').send_keys(Keys.ENTER)
time.sleep(1)
WebDriverWait(browser, 1000).until(
EC.presence_of_element_located((By.ID, 'toStationText'))
)
#输入目的地
browser.find_element_by_id('toStationText').click()
browser.find_element_by_id('toStationText').send_keys(tostation)
browser.find_element_by_id('toStationText').send_keys(Keys.ENTER)
time.sleep(5)
#将日期的只读属性去掉
js = 'document.getElementById("train_date").removeAttribute("readonly")'
browser.execute_script(js)
#去掉原本的时间
WebDriverWait(browser, 1000).until(
EC.presence_of_element_located((By.ID, 'train_date'))
)
browser.find_element_by_id("train_date").clear()
#输入出发时间
browser.find_element_by_id('train_date').send_keys(train_date)
# 等待查询按钮是否可用
WebDriverWait(browser, 1000).until(
EC.element_to_be_clickable((By.ID, 'query_ticket'))
)
searBtn = browser.find_element_by_id('query_ticket')
searBtn.click()
print('点击按钮')
if __name__ == '__main__':
option = ChromeOptions() # 实例化一个ChromeOptions对象
option.add_experimental_option('excludeSwitches', ['enable-automation']) # 以键值对的形式加入参数
option.add_experimental_option('useAutomationExtension', False)
browser = webdriver.Chrome(options=option)
# 获取响应
browser.get('https://kyfw.12306.cn/otn/resources/login.html')
script = 'Object.defineProperty(navigator,"webdriver",{get:()=>undefined,});'
browser.execute_script(script)
browser.maximize_window()
time.sleep(1)
# 点击账号登陆
browser.find_element_by_class_name('login-hd-account').click()
#登陆12306的账号密码
login('用户名','密码')
time.sleep(4)
#例buy_ticket('南昌','抚州北','2020-12-15','D2241','xx')
buy_ticket('起始地','目的地','出发日期','车次','姓名')
想要获取更多Python学习资料可以加
QQ:2955637827私聊
或加Q群630390733
大家一起来学习讨论吧!
Python实现全自动购买火车票!抢票回家过年咯的更多相关文章
- 春运到了,带你用python来抢票回家!
不知不觉,一年一度的春运抢票大幕已经拉开,想快速抢到回家的车票吗?作为程序员,这些技术手段,你一定要知道. 为了让大家更快捷更便利的抢火车票,各种各样的抢票软件应需而生,这类软件大部分都是付费抢票的机 ...
- 火车票抢票API 根据乘客的车次与座席要求快速订票出票
火车票抢票API 根据乘客的车次与座席要求快速订票出票:https://www.juhe.cn/docs/api/id/257 1.站站查询 接口地址:http://v.juhe.cn/grabTic ...
- python 并发编程 多进程 模拟抢票
抢票是并发执行 多个进程可以访问同一个文件 多个进程共享同一文件,我们可以把文件当数据库,用多个进程模拟多个人执行抢票任务 db.txt {"count": 1} 并发运行,效率高 ...
- 实测两款 GitHub 开源抢票插件,所有坑都帮你踩过了
如果你对自己手速和市面上的各种 “加速包” 都没什么信心的话,不妨试试用程序员的手段抢票? 况且,[12306 官方宣布屏蔽了一大批付费抢票软件],这也意味着你即使给这些软件付了会员费,也依旧抢不到票 ...
- 四、基于HTTPS协议的12306抢票软件设计与实现--水平DNS并发查询分享
一.基于HTTPS协议的12306抢票软件设计与实现--实现效果 二.基于HTTPS协议的12306抢票软件设计与实现--相关接口以及数据格式 三.基于HTTPS协议的12306抢票软件设计与实现-- ...
- 智行火车票免费加速到VIP最高速抢票(不用朋友积攒或者购买加速包)
更新: 2018.11.07, 昨天我买火车票,已经不行了,这个bug已经没有了,被修复了, 望大家知悉!!! 智行火车票免费加速到VIP最高速抢票(不用朋友积攒或者购买加速包) 1)下过单后选择抢到 ...
- 用Python抢到回家的车票,so easy!
“ 盼望着,盼望着,春节的脚步近了,然而,每年到这个时候,最难的,莫过于一张回家的火车票. 据悉,今年春运期间,全国铁路发送旅客人次同比将增长 8.0%.达到 4.4 亿人次. 2020 年铁 ...
- 简单的Python 火车抢票程序
当你想查询一下火车票信息的时候,你还在上12306官网吗?或是打开你手机里的APP?下面让我们来用Python写一个命令行版的火车票查看器, 只要在命令行敲一行命令就能获得你想要的火车票信息!如果你刚 ...
- Python操作12306抢票脚本
有一段时间没有使用Python了,前几天经朋友提起一篇关于用Python实现抢火车票的文章,百度了实现抢火车票的技术细节,网上却有不少资料,也不是新鲜的东西.在了解了一些技术手段,阅读了一些大神的博文 ...
随机推荐
- python+selenium下载和上传文件
操作浏览器上传文件,先看代码 1 """ 2 * send_keys() 指定文件上传路径. 3 """ 4 from selenium i ...
- Java蓝桥杯练习题——求小数n位后3个数
求整数除法小数点后第n位开始的3位数 位数不足的补0,如0.125小数第3位后三位:0.12500→500 输入格式:a b n,空格分开,a是被除数,b是除数,n是小数后的位置 输出格式:3位数字, ...
- CentOS下搭建文件共享服务
nfs部署以及优化 Server端配置 安装rpm服务包 yum install -y nfs-utils 创建数据挂载点 mkdir -p /data 编辑exports文件 vi /etc/exp ...
- NOIP2020退役记
Day 0 这一次因为疫情仍然没有试机,但是允许提前打开虚拟机,减少了调试虚拟机的时间 开考时,吸取上一次 \(CSP\) 的教训,先把题面看了一遍 感觉 \(T1\) 比较可做,剩下的暂时没有思路 ...
- moviepy音视频剪辑VideoClip类fl_image方法image_func报错ValueError: assignment destination is read-only解决办法
☞ ░ 前往老猿Python博文目录 ░ moviepy音视频剪辑模块的视频剪辑基类VideoClip的fl_image方法用于进行对剪辑帧数据进行变换. 调用语法:fl_image(self, im ...
- Python中函数的参数带星号是什么意思?
参数带星号表示支持可变不定数量的参数,这种方法叫参数收集. 星号又可以带1个或2个,带1个表示按位置来收集参数,带2个星号表示按关键字来收集参数. 1.带一个星号的参数收集模式: 这种模式是在函数定义 ...
- PyQt(Python+Qt)学习随笔:QListView的uniformItemSizes属性
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QListView的uniformItemSizes属性用于控制视图中所有项是否具有相同大小,只有在 ...
- PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox增加自定义按钮的方法
在Qt Designer中可以预先定义标准按钮,相关支持的标准按钮请见<PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的StandardButton ...
- 关于RequestParam在不同的Spring版本上,接口在controller重载时注解可能失效的踩坑记录
先抛背景: 我项目中的Spring版本是2.0.3.RELEASE. api-demo负责暴露接口,service-demo负责实现功能.接口参数的@RequestParam和@RequestBody ...
- HTTP慢速拒绝服务攻击(Slow HTTP Dos)
HTTP慢速拒绝服务攻击简介 HTTP慢速攻击是利用HTTP合法机制,以极低的速度往服务器发送HTTP请求,尽量长时间保持连接,不释放,若是达到了Web Server对于并发连接数的上限,同时恶意占用 ...