python实现自动登录12306抢票 -- selenium

关于使用selenium实现12306登陆,并登录之后通过12306进行预订买票的一个操作
本程序并不鼓励各位读者违反12306平台的使用条款及相关法律规定!
本文章仅作为学习交流和提供思路使用!
相关重要程序已对部分代码进行模糊处理!
1
进入12306







12345
- 首先进入到12306 找到要购买的车次 如图1所示
- 如图2所示 右键->检查 或者按f12打开 在左侧搜索车次, 点击右侧的response这个里面就是返回的值大家可以看一下
- 如图3所示 点击Heards 向下滑动 找到 user-agent:进行复制
- 注意图4的这个url就是后面要访问的地址
- 还有如图5所示的cookie 后面也是需要替换更改的
2
12306城市名对应字母缩写

这是对应名称的地址编号到时候放进去
city_all.json
49.56KB
3
获取json

import requests
import json
"""
发送请求:模拟浏览器对于url地址发送请求
"""
"""根据用户自行输入相关信息,进行查票搜索"""
# 读取城市文件 该文件在第二步
f = open('city_all.json', encoding='utf-8').read()
city_data = json.loads(f)
print(city_data)
# 输入出发和目的城市
# 输入时间
train_date = '2025-01-09'
from_city = input('请输出你出发的城市:')
to_city = input('请输出你要出行的城市:')
print('您出发的城市为:'+city_data[from_city])
print('您的目的地为:'+city_data[to_city])
headers = {
// cookie 看步骤1进行复制 然后自行进行替换变量即可
'cookie': f '_uab_collina=173586775383533785851595; JSESSIONID=C4EC2E1E32BBA03480E951D04713396E; BIGipServerotn=1540948234.64545.0000; BIGipServerpassport=937951498.50215.0000; guidesStatus=off; highContrastMode=defaltMode; cursorStatus=off; route=495c805987d0f5c8c84b14f60212447d; _jc_save_fromStation=%u5317%u4EAC%2CBJP; _jc_save_toStation=%u90AF%u90F8%u4E1C%2CHPP; _jc_save_fromDate={train_date}; _jc_save_toDate={train_date}; _jc_save_wfdc_flag=wf',
// 写死这个即可
"content-type": "application/json",
// 看步骤1进行复制 然后自行进行替换变量即可
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
}
# 请求网址 看步骤1进行复制
url = f'https://kyfw.12306.cn/otn/leftTicket/queryG?leftTicketDTO.train_date={train_date}&leftTicketDTO.from_station={city_data[from_city]}&leftTicketDTO.to_station={city_data[to_city]}&purpose_codes=ADULT'
# 发送请求 使用request
response = requests.get(url=url, headers=headers)
print(url)
print(response.status_code)
# 获取数据
json_data = response.json()
print(json_data)
如图1所示
4
解析 json 数据




12
我们把杂乱的东西去除后json就如下面所示
{
// 状态码
"httpstatus": 200,
// 数据
"data": {
// 车次内容
"result": [ ],
"flag": "1",
"level": "0",
"sametlc": "Y",
// 相关车站
"map": {
"IFP": "北京朝阳",
"FTP": "北京丰台",
"HDP": "邯郸",
"HPP": "邯郸东",
"BJP": "北京",
"BXP": "北京西"
}
},
"messages": "",
"status": true
}
输入以下命令进行安装 prettytable模块可以把json变得非常的美丽
pip install prettytable
代码如下 输出效果如图所示
# 实例化对象
tb = PrettyTable()
// 表头
tb.field_names = [
'序号',
'车次',
'出发时间',
'到达时间',
'耗时',
'特等座',
'一等座',
'二等座',
'软卧',
'硬卧',
'硬座',
'无座',
]
# 定义一个打印序号page
page = 1
# for循环遍历,提取列表里面的元素
for i in json_data['data']['result']:
# 字符串分割,返回列表
index = i.split('|')
# 通过列表索引位置取值
num = index[3] # 车次
star_time = index[8] # 出发时间
arrive_time = index[9] # 到达时间
use_time = index[10] # 耗时
special_class = index[32] # 特等座
frist_class = index[31] # 一等座
second_class = index[30] # 二等座
hard_sleeper = index[28] # 硬卧
hard_seat = index[29] # 硬座
no_seat = index[26] # 无座
soft_sleeper = index[23] # 软卧
// 对应关系
dict = {
'序号': 'page',
'车次': 'num',
'出发时间': 'star_time',
'到达时间': 'arrive_time',
'耗时': 'use_time',
'特等座': 'special_class',
'一等座': 'frist_class',
'二等座': 'second_class',
'软卧': 'soft_sleeper',
'硬卧': 'hard_sleeper',
'硬座': 'hard_seat',
'无座': 'no_seat'
}
// 放到prettytable中进行美化
tb.add_row([
page, # 序号索引
num, # 车次
star_time, # 出发时间
arrive_time, # 到达时间
use_time, # 耗时
special_class, # 特等座
frist_class, # 一等座
second_class, # 二等座
soft_sleeper, # 软卧
hard_sleeper, # 硬卧
hard_seat, # 硬座
no_seat, # 无座
])
page += 1
print(tb)
5
操作浏览器进行登录





123
添加以下两个浏览器操作的模块 如图1所示
# 下面的模块就是打开浏览器的操作模块
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
右键->检查 找到登录输入框的css 如图2 图3所示 然后我们通过这个位置进行操控和输入,这步懂html的会好理解一点,图3是进行验证操作的,我就通过input进行输入了
# 登录的参数
login = {
# 账号
'account': '',
# 密码
'password': '',
# 身份证号后四位
'id_card': '',
}
# 0.配置谷歌浏览器加载项
options = webdriver.ChromeOptions()
# 0.不自动关闭浏览器
options.add_experimental_option("detach", True)
# 1.将加载项配置到启动浏览器中 打开/创建浏览器对象 注意!!! executable_path 是执行的驱动文件有的需要加有点不需要(mac不需要加我就没加)
driver = webdriver.Chrome(options=options)
# 2.输入网址
driver.get('https://kyfw.12306.cn/otn/view/index.html')
# 3.输入账号 -- > 找到账号的输入框 selenium 通过元素面板去定位元素
driver.find_element(by="css selector", value="#J-userName").send_keys(login['account'])
# 4.输入密码 -- > 找到密码的输入框
driver.find_element(by="css selector", value="#J-password").send_keys(login['password'])
# 5.点击登录按钮
driver.find_element(by="css selector", value="#J-login").click()
time.sleep(0.5)
# 6.输入身份证后4位
driver.find_element(by="css selector", value="#id_card").send_keys(login['id_card'])
# 7.点击获取验证码
driver.find_element(by="css selector", value="#verification_code").click()
# 8.输入验证码
code = input("请输入验证码:")
driver.find_element(by="css selector", value="#code").send_keys(code)
driver.find_element(by="css selector", value="#verification_code").click()
# 9.点击确认按钮
driver.find_element(by="css selector", value="#sureClick").click()
6
查询车次








123456
我们进入到的页面如图1所示,我们需要点击车票预定的这个按钮才可以进入所以我们模拟一个点击车票预定的按钮如下所示
driver.find_element(by="css selector", value="#link_for_ticket").click()
如图2所示 需要我们往出发地与目的地中填写信息
# 12 点击输入框选择出发的城市
driver.find_element(by="css selector", value="#fromStationText").click()
# 13 输入出发的城市
driver.find_element(by="css selector", value="#fromStationText").send_keys(from_city)
# 回车确认
driver.find_element(by="css selector", value="#fromStationText").send_keys(Keys.ENTER)
#######################
# 14 点击输入框选择目的地城市
driver.find_element(by="css selector", value="#toStationText").click()
# 15 输入抵达的城市
driver.find_element(by="css selector", value="#toStationText").send_keys(to_city)
# 回车确认
driver.find_element(by="css selector", value="#toStationText").send_keys(Keys.ENTER)
选择日期输入框 如图3所示 然后在点击查询即可 如图4所示
总共代码如下
login = {
'account': '',
'password': '',
'id_card': '',
}
# 抢票部分
def selenium_grab_tickets():
# 0.配置谷歌浏览器加载项
options = webdriver.ChromeOptions()
# 不自动关闭浏览器
options.add_experimental_option("detach", True)
# 1.将加载项配置到启动浏览器中 打开/创建浏览器对象 executable_path 是执行的驱动文件有的需要加有点不需要
driver = webdriver.Chrome(options=options)
# 2.输入网址
driver.get('https://kyfw.12306.cn/otn/view/index.html')
# 3.输入账号 -- > 找到账号的输入框 selenium 通过元素面板去定位元素
driver.find_element(by="css selector", value="#J-userName").send_keys(login['account'])
# 4.输入密码 -- > 找到密码的输入框
driver.find_element(by="css selector", value="#J-password").send_keys(login['password'])
# 5.点击登录按钮
driver.find_element(by="css selector", value="#J-login").click()
time.sleep(0.5)
# 6.输入身份证后4位
driver.find_element(by="css selector", value="#id_card").send_keys(login['id_card'])
# 7.点击获取验证码
driver.find_element(by="css selector", value="#verification_code").click()
# 8.输入验证码
code = input("请输入验证码:")
driver.find_element(by="css selector", value="#code").send_keys(code)
driver.find_element(by="css selector", value="#verification_code").click()
# 9.点击确认按钮
driver.find_element(by="css selector", value="#sureClick").click()
# 用 driver.implicitly_wait()代码 可以实现加载完就就进行下一步,
driver.implicitly_wait(5)
# 10,点击车票预定的按钮
driver.find_element(by="css selector", value="#link_for_ticket").click()
# 12 点击输入框选择出发的城市
driver.find_element(by="css selector", value="#fromStationText").click()
# 13 输入出发的城市
driver.find_element(by="css selector", value="#fromStationText").send_keys(from_city)
# 进行回车
driver.find_element(by="css selector", value="#fromStationText").send_keys(Keys.ENTER)
# 14 点击输入框选择目的地城市
driver.find_element(by="css selector", value="#toStationText").click()
# 15 输入抵达的城市
driver.find_element(by="css selector", value="#toStationText").send_keys(to_city)
# 进行回车
driver.find_element(by="css selector", value="#toStationText").send_keys(Keys.ENTER)
# 16 点击选择出发的日期输入框
driver.find_element(by="css selector", value="#train_date").clear()
# 17 选择出发的日期
driver.find_element(by="css selector", value="#train_date").send_keys(train_date)
# 18 选择出发的日期--回车确定
driver.find_element(by="css selector", value="#train_date").send_keys(Keys.ENTER)
# 19 点击查询
driver.find_element(by="css selector", value="#query_ticket").click()
driver.implicitly_wait(5)
# 20 点击--显示全部可预订的车次
driver.find_element(by="css selector", value="#avail_ticket").click()
查询出来效果如图6所示
7
购买车票






1234
- 如图1所示 有用预定按钮是没有id的 我们就只能通过下标的方式来进行模拟点击操作所以输入的是序号
# 因为预约按钮没有id我们就只能通过序号来进行操作
num = int(input('请输入您想要的车次序号:'))
# 预约按钮没有办法通过id进行点击只能通过这种方式
ticket_list = driver.find_elements(by="xpath",
value='//div//tbody[@id="queryLeftTable"]/tr[contains(@id,"ticket")]')
ticket_num = ticket_list[num].get_attribute("id")
ticket_pre = ticket_num + ' > td.no-br'
# 21 点击想要车次的预定按钮
driver.find_element(by="css selector", value=f"#{ticket_pre}").click()
后面就按照根据id进行点击往下走即可 如图2-4所示 代码如下
# 因为预约按钮没有id我们就只能通过序号来进行操作
num = int(input('请输入您想要的车次序号:'))
# 预约按钮没有办法通过id进行点击只能通过这种方式
ticket_list = driver.find_elements(by="xpath",
value='//div//tbody[@id="queryLeftTable"]/tr[contains(@id,"ticket")]')
ticket_num = ticket_list[num].get_attribute("id")
ticket_pre = ticket_num + ' > td.no-br'
# 21 点击想要车次的预定按钮
driver.find_element(by="css selector", value=f"#{ticket_pre}").click()
# 22 勾选想要的乘车人
driver.find_element(by="css selector", value='#normalPassenger_0').click()
#
#
# 23 提交订单
driver.find_element(by="css selector", value='#submitOrder_id').click()
driver.implicitly_wait(5)
# 24 选择靠窗的1F的位置
driver.find_element(by="css selector", value='#erdeng1 > ul:nth-child(4) > li:nth-child(2)').click()
#
# 25 再次确认提交
driver.implicitly_wait(5)
driver.find_element(by="css selector", value='#qr_submit_id').click()
# 26. 网上支付 -- payButton
# driver.find_element(by="css selector", value='#payButton').click()
# 27. 取消订单 -- cancelButton
driver.find_element(by="css selector", value='#cancelButton').click()
8
完整代码

import json
import time
import requests
from prettytable import PrettyTable
# 下面的模块就是打开浏览器的操作模块
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
"""
发送请求:模拟浏览器对于url地址发送请求
"""
"""根据用户自行输入相关信息,进行查票搜索"""
# 读取城市文件
f = open('city_all.json', encoding='utf-8').read()
city_data = json.loads(f)
print(city_data)
# 输入出发和目的城市
# 输入时间
train_date = '2025-01-09'
from_city = '北京'
to_city = '邯郸'
print(city_data[from_city])
print(city_data[to_city])
headers = {
'cookie':
f'_uab_collina=173586775383533785851595; JSESSIONID=C4EC2E1E32BBA03480E951D04713396E; '
f'BIGipServerotn=1540948234.64545.0000; BIGipServerpassport=937951498.50215.0000; guidesStatus=off; '
f'highContrastMode=defaltMode; cursorStatus=off; route=495c805987d0f5c8c84b14f60212447d; '
f'_jc_save_fromStation=%u5317%u4EAC%2CBJP; _jc_save_toStation=%u90AF%u90F8%u4E1C%2CHPP; _jc_save_fromDate='
f'{train_date}; _jc_save_toDate={train_date}; _jc_save_wfdc_flag=wf',
"content-type": "application/json",
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/131.0.0.0 Safari/537.36',
}
# 请求网址
url = f'https://kyfw.12306.cn/otn/leftTicket/queryG?leftTicketDTO.train_date={train_date}&leftTicketDTO.from_station={city_data[from_city]}&leftTicketDTO.to_station={city_data[to_city]}&purpose_codes=ADULT'
# 发送请求 使用request
response = requests.get(url=url, headers=headers)
print(url)
print(response.status_code)
print(response.text)
# 获取数据
json_data = response.json()
# 解析数据--字典取值:
result = json_data['data']['result']
def print_ticketlist():
# 实例化对象
tb = PrettyTable()
tb.field_names = [
'序号',
'车次',
'出发时间',
'到达时间',
'耗时',
'特等座',
'一等座',
'二等座',
'软卧',
'硬卧',
'硬座',
'无座',
]
# 定义一个打印序号page
page = 1
# for循环遍历,提取列表里面的元素
for i in result:
# 字符串分割,返回列表
index = i.split('|')
# 通过列表索引位置取值
num = index[3] # 车次
star_time = index[8] # 出发时间
arrive_time = index[9] # 到达时间
use_time = index[10] # 耗时
special_class = index[32] # 特等座
frist_class = index[31] # 一等座
second_class = index[30] # 二等座
hard_sleeper = index[28] # 硬卧
hard_seat = index[29] # 硬座
no_seat = index[26] # 无座
soft_sleeper = index[23] # 软卧
# {
# '序号': 'page',
# '车次': 'num',
# '出发时间': 'star_time',
# '到达时间': 'arrive_time',
# '耗时': 'use_time',
# '特等座': 'special_class',
# '一等座': 'frist_class',
# '二等座': 'second_class',
# '软卧': 'soft_sleeper',
# '硬卧': 'hard_sleeper',
# '硬座': 'hard_seat',
# '无座': 'no_seat'
#
# }
tb.add_row([
page, # 序号索引
num, # 车次
star_time, # 出发时间
arrive_time, # 到达时间
use_time, # 耗时
special_class, # 特等座
frist_class, # 一等座
second_class, # 二等座
soft_sleeper, # 软卧
hard_sleeper, # 硬卧
hard_seat, # 硬座
no_seat, # 无座
])
page += 1
print(tb)
# 抢票部分
def selenium_grab_tickets():
login = {
'account': '',
'password': '',
'id_card': '',
}
# 0.配置谷歌浏览器加载项
options = webdriver.ChromeOptions()
# 不自动关闭浏览器
options.add_experimental_option("detach", True)
# 1.将加载项配置到启动浏览器中 打开/创建浏览器对象 executable_path 是执行的驱动文件有的需要加有点不需要
driver = webdriver.Chrome(options=options)
# 2.输入网址
driver.get('https://kyfw.12306.cn/otn/view/index.html')
# 3.输入账号 -- > 找到账号的输入框 selenium 通过元素面板去定位元素
driver.find_element(by="css selector", value="#J-userName").send_keys(login['account'])
# 4.输入密码 -- > 找到密码的输入框
driver.find_element(by="css selector", value="#J-password").send_keys(login['password'])
# 5.点击登录按钮
driver.find_element(by="css selector", value="#J-login").click()
time.sleep(0.5)
# 6.输入身份证后4位
driver.find_element(by="css selector", value="#id_card").send_keys(login['id_card'])
# 7.点击获取验证码
driver.find_element(by="css selector", value="#verification_code").click()
# 8.输入验证码
code = input("请输入验证码:")
driver.find_element(by="css selector", value="#code").send_keys(code)
driver.find_element(by="css selector", value="#verification_code").click()
# 9.点击确认按钮
driver.find_element(by="css selector", value="#sureClick").click()
# 用 driver.implicitly_wait()代码 可以实现加载完就就进行下一步,
driver.implicitly_wait(5)
# 10,点击车票预定的按钮
driver.find_element(by="css selector", value="#link_for_ticket").click()
# 12 点击输入框选择出发的城市
driver.find_element(by="css selector", value="#fromStationText").click()
# 13 输入出发的城市
driver.find_element(by="css selector", value="#fromStationText").send_keys(from_city)
# 进行回车
driver.find_element(by="css selector", value="#fromStationText").send_keys(Keys.ENTER)
# 14 点击输入框选择目的地城市
driver.find_element(by="css selector", value="#toStationText").click()
# 15 输入抵达的城市
driver.find_element(by="css selector", value="#toStationText").send_keys(to_city)
# 进行回车
driver.find_element(by="css selector", value="#toStationText").send_keys(Keys.ENTER)
# 16 点击选择出发的日期输入框
driver.find_element(by="css selector", value="#train_date").clear()
# 17 选择出发的日期
driver.find_element(by="css selector", value="#train_date").send_keys(train_date)
# 18 选择出发的日期--回车确定
driver.find_element(by="css selector", value="#train_date").send_keys(Keys.ENTER)
# 19 点击查询
driver.find_element(by="css selector", value="#query_ticket").click()
driver.implicitly_wait(5)
# 20 点击--显示全部可预订的车次
driver.find_element(by="css selector", value="#avail_ticket").click()
# 因为预约按钮没有id我们就只能通过序号来进行操作
num = int(input('请输入您想要的车次序号:'))
# 预约按钮没有办法通过id进行点击只能通过这种方式
ticket_list = driver.find_elements(by="xpath",
value='//div//tbody[@id="queryLeftTable"]/tr[contains(@id,"ticket")]')
ticket_num = ticket_list[num].get_attribute("id")
ticket_pre = ticket_num + ' > td.no-br'
# 21 点击想要车次的预定按钮
driver.find_element(by="css selector", value=f"#{ticket_pre}").click()
# 22 勾选想要的乘车人
driver.find_element(by="css selector", value='#normalPassenger_0').click()
#
#
# 23 提交订单
driver.find_element(by="css selector", value='#submitOrder_id').click()
driver.implicitly_wait(5)
# 24 选择靠窗的1F的位置
driver.find_element(by="css selector", value='#erdeng1 > ul:nth-child(4) > li:nth-child(2)').click()
#
# 25 再次确认提交
time.sleep(5)
driver.find_element(by="css selector", value='#qr_submit_id').click()
# 26. 网上支付 -- payButton
# driver.find_element(by="css selector", value='#payButton').click()
# 27. 取消订单 -- cancelButton
driver.find_element(by="css selector", value='#cancelButton').click()
if __name__ == "__main__":
print_ticketlist()
selenium_grab_tickets()
再次声明:本程序只用作学习交流使用,部分代码已经模糊处理,请遵守相关法律规定!








更多相关项目
猜你喜欢
评论/提问(已发布 0 条)

