自动化抢票 12306
自动化抢票 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()
相关文章:
自动化抢票 12306
自动化抢票 12306 1. 明确需求 明确采集的网站以及数据内容 网址: https://kyfw.12306.cn/otn/leftTicket/init数据: 车次相关信息 2. 抓包分析 通过浏览器开发者工具分析对应的数据位置 打开开发者工具 F12 或鼠标右键点击检查 刷新网页 点击下一页/下滑网页页面/点击搜…...

海外云服务器安装 MariaDB10.6.X (Ubuntu 18.04 记录篇二)
本文首发于 秋码记录 MariaDB 的由来(历史) 谈起新秀MariaDB,或许很多人都会感到陌生吧,但若聊起享誉开源界、业界知名的关系型数据库——Mysql,想必混迹于互联网的人们(coder)无不知晓。 其…...
Mybatis_基础
文章目录 第一章 Mybatis简介1.1 Mybatis特性1.2 和其它持久化层技术对比 第二章 Mybatis的增删改查第三章 Mybatis的增删改查 第一章 Mybatis简介 1.1 Mybatis特性 MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和…...
8Manage采购申请管理:轻松实现手动采购流程自动化
您是否感受到通过手动采购申请流程管理成本的压力? 信息的不充分常常导致现金流的不透明,这已成为财务高管们的常见痛点。本文将展示采购申请管理软件如何帮助您减轻负担,使您能够简化流程。 没有采购申请软件会面临哪些挑战? …...

PADS Router 入门基础教程(一)
有将近三周没有更新过博客了,最近在整理PADS Router 入门基础教程,希望喜欢本系列教程的小伙伴可以点点关注和订阅!下面我们开始进入PADS Router课程的介绍。 一、PADS Router 快捷键 二、课程介绍 本教程主要介绍:PADS Rou…...

一台手机一个ip地址吗?手机ip地址泄露了怎么办
在数字化时代,手机作为我们日常生活中不可或缺的一部分,其网络安全性也日益受到关注。其中一个常见的疑问便是:“一台手机是否对应一个固定的IP地址?”实际上,情况并非如此简单。本文首先解答这一问题&a…...

【扇贝编程】使用Selenium模拟浏览器获取动态内容笔记
文章目录 selenium安装 selenium下载浏览器驱动 获取数据处理数据查找一个元素查找所有符合条件的元素 控制浏览器 selenium selenium是爬虫的好帮手, 可以控制你的浏览器,模仿人浏览网页,从而获取数据,自动操作等。 我们只要让…...

TCP Analysis Flags 之 TCP Port numbers reused
前言 默认情况下,Wireshark 的 TCP 解析器会跟踪每个 TCP 会话的状态,并在检测到问题或潜在问题时提供额外的信息。在第一次打开捕获文件时,会对每个 TCP 数据包进行一次分析,数据包按照它们在数据包列表中出现的顺序进行处理。可…...

【Python机器学习】核心数、进程、线程、超线程、L1、L2、L3级缓存
如何知道自己电脑的CPU是几核的,打开任务管理器(同时按下:Esc键、SHIFT键、CTRL键) 然后,点击任务管理器左上角的性能选项,观察右下角中的内核:后面的数字,就是你CPU的核心数,下图中我的是16个核心的。 需要注意的是,下面的逻辑处理器:32 表示支持 32 线程(即超线…...

JavaScript使用地理位置 API
前言 在JavaScript中,Geolocation API 是一种用于访问用户地理位置的接口。这个API允许网页应用程序获取用户的位置并提供基于位置的服务。 if (navigator.geolocation)navigator.geolocation.getCurrentPosition(function () {},function () {});这个函数中需要传…...
dockerfile部署fastapi项目
dockerfile部署fastapi项目 1、Dockerfile # 使用Python官方镜像作为基础镜像 FROM python:3.8-slim# 更新apt-get源并安装依赖 # RUN apt-get update -y && apt-get install -y git# 设置环境变量 ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1# 创建工作目…...

火语言RPA流程组件介绍--浏览网页
🚩【组件功能】:浏览器打开指定网址或本地html文件 配置预览 配置说明 网址URL 支持T或# 默认FLOW输入项 输入需要打开的网址URL 超时时间 支持T或# 打开网页超时时间 执行后后等待时间(ms) 支持T或# 当前组件执行完成后继续等待的时间 UserAgen…...

【Linux系统学习】2.Linux基础命令
Linux基础命令 Linux的目录结构 Linux命令入门 目录切换相关命令(cd/pwd) 相对路径、绝对路径和特殊路径符 创建目录命令(mkdir) 文件操作命令part1(touch、cat、more) 文件操作命令part2(cp、mv、rm) 查找命令(which、find) grep、wc和管道符…...

ABAP正则表达式 特殊字符处理
REPLACE ALL OCCURRENCES OF REGEX [[:space:]] IN <fs_purhdinfo>-cell_value WITH ."可去掉空格或回车键 REPLACE ALL OCCURRENCES OF : IN <fs_purhdinfo>-cell_value WITH ."可去掉空格或回车键 REPLACE ALL OCCURRENCES OF R…...

【2024高教社杯全国大学生数学建模竞赛】ABCDEF题 问题分析、模型建立、参考文献及实现代码
【2024高教社杯全国大学生数学建模竞赛】ABCDEF题 问题分析、模型建立、参考文献及实现代码 1 比赛时间 北京时间:2024年9月5日 18:00-2024年9月8日20:00 2 思路内容 2.1 往届比赛资料 【2022高教社杯数学建模】C题:古代玻璃制品的成分分析与鉴别方案…...

# VMware 共享文件
VMware tools快速安装 VMware 提供了 open-vm-tools,这是 VMware 官方推荐的开源工具包,通常不需要手动安装 VMware Tools,因为大多数 Linux 发行版(包括 Ubuntu、CentOS 等)都包含了 open-vm-tools,并且已…...

[UVM]3.核心基类 uvm_object 域的自动化 copy() compare() print() pack unpack
1.核心基类:uvm_object (1)虚类只能声明,不能例化。 (2)uvm_object提供的方法 2.域的自动化(field automation) (1)简述 (2)示例 格…...
Java网络编程入门
在现代软件开发中,网络编程是一项不可或缺的技能。Java提供了强大的网络编程支持,使得开发者能够轻松地创建网络应用程序。今天将介绍Java中的网络编程基础,重点讲解Socket和ServerSocket类的使用。 什么是Socket? Socket是网络通…...
前端基础面试题·第三篇——JavaScript(其一)
1.JavaScript数据类型与运算符 数据类型 原始数据类型: 1.Number 2.String 3.Boolean 4.undefined 5.null 6.Symbol 7.bigint 复杂数据类型: 1.Function 2.非函数: Array: 数组 Object: 对象 Date: 日期 RegExp: 正则 Map: 映射 Set: 集合 …...

【机器学习】生成对抗网络(Generative Adversarial Networks, GANs)详解
1.引言 生成对抗网络(Generative Adversarial Networks, GANs)是近年来人工智能领域最具创新性和颠覆性的模型之一。自2014年由Ian Goodfellow及其团队提出以来,GAN的出现彻底改变了生成模型的研究范式。传统的生成模型,如变分自编码器(VAE)、隐马尔可夫模型(HMM)等,…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...