首页 > Python资料 博客日记
自动化抢票 12306
2024-09-15 01:00:09Python资料围观40次
本篇文章分享自动化抢票 12306,对你有帮助的话记得收藏一下,看Python资料网收获更多编程知识
注意!!!代码仅供学习和参考,不要用做非法用途!!!
自动化抢票 12306
1. 明确需求
明确采集的网站以及数据内容
- 网址: https://kyfw.12306.cn/otn/leftTicket/init
- 数据: 车次相关信息
2. 抓包分析
通过浏览器开发者工具分析对应的数据位置
- 打开开发者工具
- F12 或鼠标右键点击检查
- 刷新网页
- 点击下一页/下滑网页页面/点击搜索/查询按钮
- 让网页相关数据内容加载出来 (整个网站数据内容重新加载一遍)
- 通过关键字搜索找到对应数据位置
- 需要什么数据就搜什么
数据包地址: https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2024-09-06&leftTicketDTO.from_station=IZQ&leftTicketDTO.to_station=SNQ&purpose_codes=ADULT
3. 代码实现步骤
1. 发送请求
模拟浏览器对于 url 地址发送请求
-
模拟浏览器
- 可以直接复制,使用请求标头中参数内容
- 去哪里找: 开发者工具 -> 网络 -> 点击对应数据包 -> 标头 -> 请求标头(参数)
- 怎么写: 使用字典接受数据内容 (构建完整的键值对)
-
请求网址
- 通过抓包分析找到链接地址,直接复制即可
-
发送请求
- 使用第三方模块: requests
- 安装 requests 模块
- win+r 输入 cmd 点击确定,输入安装命令:
pip install requests
- win+r 输入 cmd 点击确定,输入安装命令:
- 导入 requests 模块
- 请求方法: 开发者工具 -> 网络 -> 点击对应数据包 -> 标头 -> 常规
- GET 请求参数: 查询参数 (直接在链接中就有)
- 安装 requests 模块
- 使用第三方模块: requests
2. 获取数据
获取服务器返回响应数据
- 12306 的请求参数并不是简单的中文字符,而是对应的三字编码,我们需要找到对应的编码
- 对网页分析发现,在一个 js 文件中可以获取
- 在页面最后有
https://kyfw.12306.cn/otn/resources/js/framework/station_name.js
链接
3. 解析数据
提取我们需要的数据内容: 车次相关内容
4. 保存数据
- 字典取值
- 键值对取值: 根据冒号左边的内容 [“键”, 提取冒号右边的内容 [“值”]]
当然,下面我将重点介绍每个步骤的关键点,并附上相应的代码片段。
1. 获取站点编码
关键点:从 12306 的 JS 文件中解析站点的三字码。
代码片段:
def get_station_codes():
code_url = "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js"
response = requests.get(code_url)
code_data = response.text[20:-2] # 优化:去除尾部的双引号和换行符
list_code = code_data.split("|")
station_codes = dict(zip(list_code[1::5], list_code[2::5])) # 优化:直接跳过索引获取站点名称和代码
return station_codes
2. 用户输入
关键点:提示用户输入起始站、终点站和出发日期,然后转换为 12306 需要的编码。
代码片段:
def get_user_input(code_dic):
from_station = input("输入起始站:\n")
to_station = input("输入终点站:\n")
time = input("输入时间,例如:2024-09-18:\n")
return code_dic.get(from_station, ""), code_dic.get(to_station, ""), time
3. 获取火车票信息
关键点:构建请求 URL,模拟浏览器发送 HTTP 请求获取数据。
代码片段:
def get_train_info(from_station, to_station, time):
train_url = f"https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date={time}&leftTicketDTO.from_station={from_station}&leftTicketDTO.to_station={to_station}&purpose_codes=ADULT"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
}
response = requests.get(url=train_url, headers=headers)
return response.json()
4. 打印火车票信息
关键点:解析服务器返回的 JSON 数据,并使用PrettyTable
格式化输出。
代码片段:
def print_train_info(json_data):
table = PrettyTable()
table.field_names = ['车次', '出发时间', '到达时间', '历时', '一等座', '二等座', '特等座']
if json_data['httpstatus'] == 200:
result = json_data['data']['result']
for item in result:
details = item.split('|')
table.add_row([details[3], details[8], details[9], details[10], details[30], details[31], details[32]])
print(table)
else:
print(f"获取响应数据失败,状态码为{json_data['httpstatus']}")
5. Selenium 自动化
关键点:使用 Selenium 模拟用户在网页上的操作,如填写表单、点击按钮等。
代码片段:
def main():
# 获取站点编码
code_dic = get_station_codes()
# 获取用户输入
from_station_code, to_station_code, time = get_user_input(code_dic)
# 使用Selenium打开网页
browser = webdriver.Edge()
browser.get('https://kyfw.12306.cn/otn/leftTicket/init')
# 填写查询表单
start_station = browser.find_element(By.CSS_SELECTOR, '#fromStationText')
start_station.send_keys("广州南")
start_station.send_keys(Keys.ENTER)
end_station = browser.find_element(By.CSS_SELECTOR, '#toStationText')
end_station.send_keys("韶关")
end_station.send_keys(Keys.ENTER)
date = browser.find_element(By.CSS_SELECTOR, '#train_date')
date.send_keys("2024-09-18")
date.send_keys(Keys.ENTER)
# 点击查询
browser.find_element(By.CSS_SELECTOR, '#query_ticket').click()
# 等待查询结果
t.sleep(5) # 优化:使用更明确的等待条件
# 处理查询结果
# 省略:根据实际情况处理查询结果
# 关闭浏览器
browser.quit()
6. 完整代码
# coding=gbk
import time as t
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from prettytable import PrettyTable
import re
# 获取站点对应的三字码
def get_station_codes():
code_url = "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js"
response = requests.get(code_url)
code_data = response.text[20:-2] # 优化:去除尾部的双引号和换行符
list_code = code_data.split("|")
station_codes = dict(zip(list_code[1::5], list_code[2::5])) # 优化:直接跳过索引获取站点名称和代码
return station_codes
# 用户输入起始站、终点站和时间,转化为编码
def get_user_input(code_dic):
from_station = input("输入起始站:\n")
to_station = input("输入终点站:\n")
time = input("输入时间,例如:2024-09-18:\n")
return code_dic.get(from_station, ""), code_dic.get(to_station, ""), time
# 获取火车票信息
def get_train_info(from_station, to_station, time):
train_url = f"https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date={time}&leftTicketDTO.from_station={from_station}&leftTicketDTO.to_station={to_station}&purpose_codes=ADULT"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
}
response = requests.get(url=train_url, headers=headers)
return response.json()
# 打印火车票信息
def print_train_info(json_data):
table = PrettyTable()
table.field_names = ['车次', '出发时间', '到达时间', '历时', '一等座', '二等座', '特等座']
if json_data['httpstatus'] == 200:
result = json_data['data']['result']
for item in result:
details = item.split('|')
table.add_row([details[3], details[8], details[9], details[10], details[30], details[31], details[32]])
print(table)
else:
print(f"获取响应数据失败,状态码为{json_data['httpstatus']}")
# 主函数
def main():
# 获取站点编码
code_dic = get_station_codes()
# 获取用户输入
from_station, to_station, time = get_user_input(code_dic)
# 获取火车票信息
json_data = get_train_info(from_station, to_station, time)
# 打印火车票信息
print_train_info(json_data)
# 使用Selenium打开网页
browser = webdriver.Edge()
browser.get('https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc')
# 填写查询表单
start_station = browser.find_element(By.CSS_SELECTOR, '#fromStationText')
start_station.clear()
start_station.send_keys("广州南")
start_station.send_keys(Keys.ENTER)
end_station = browser.find_element(By.CSS_SELECTOR, '#toStationText')
end_station.clear()
end_station.send_keys("韶关")
end_station.send_keys(Keys.ENTER)
date = browser.find_element(By.CSS_SELECTOR, '#train_date')
date.clear()
date.send_keys("2024-09-18")
date.send_keys(Keys.ENTER)
# 点击查询
browser.find_element(By.CSS_SELECTOR, '#query_ticket').click()
# 等待查询结果
t.sleep(5) # 优化:使用更明确的等待条件
# 处理查询结果
elements = browser.find_elements(By.CSS_SELECTOR, '#queryLeftTable tr:nth-child(7) .btn72')
if elements:
elements[0].click()
# 扫码登陆
saoma = browser.find_element(By.CSS_SELECTOR, '#login > div.login-box > ul > li.login-hd-account > a')
saoma.click()
t.sleep(5) # 优化:使用更明确的等待条件
# 登录操作
J_userName = browser.find_element(By.CSS_SELECTOR, '#J-userName')
J_userName.clear()
J_userName.send_keys("aaa")
J_password = browser.find_element(By.CSS_SELECTOR, '#J-password')
J_password.clear()
J_password.send_keys("password")
J_loginmodalBtn = browser.find_element(By.CSS_SELECTOR, '#J-login')
J_loginmodalBtn.click()
# 点击预订
browser.find_element(By.CSS_SELECTOR, '#normalPassenger_0').click()
t.sleep(1)
browser.find_element(By.CSS_SELECTOR, '#dialog_xsertcj_cancel').click()
# 修改成人票
ticket_type_select = browser.find_element(By.CSS_SELECTOR, '#ticketType_1')
ticket_type_select.click()
# 选择成人票
adult_ticket_option = browser.find_element(By.CSS_SELECTOR, '#ticketType_1 > option[value="1"]')
adult_ticket_option.click()
t.sleep(1)
browser.find_element(By.CSS_SELECTOR, '#submitOrder_id').click()
qr_submit_id = browser.find_element(By.CSS_SELECTOR, '#qr_submit_id')
if qr_submit_id:
qr_submit_id.click()
input("输入任意字符后回车继续...")
# 关闭浏览器
browser.quit()
if __name__ == "__main__":
main()
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
相关文章
最新发布
- 【Python】selenium安装+Microsoft Edge驱动器下载配置流程
- Python 中自动打开网页并点击[自动化脚本],Selenium
- Anaconda基础使用
- 【Python】成功解决 TypeError: ‘<‘ not supported between instances of ‘str’ and ‘int’
- manim边学边做--三维的点和线
- CPython是最常用的Python解释器之一,也是Python官方实现。它是用C语言编写的,旨在提供一个高效且易于使用的Python解释器。
- Anaconda安装配置Jupyter(2024最新版)
- Python中读取Excel最快的几种方法!
- Python某城市美食商家爬虫数据可视化分析和推荐查询系统毕业设计论文开题报告
- 如何使用 Python 批量检测和转换 JSONL 文件编码为 UTF-8
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Python与PyTorch的版本对应
- Anaconda版本和Python版本对应关系(持续更新...)
- Python pyinstaller打包exe最完整教程
- Could not build wheels for llama-cpp-python, which is required to install pyproject.toml-based proj