当前位置: 首页 > news >正文

自动化抢票 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
      • 导入 requests 模块
      • 请求方法: 开发者工具 -> 网络 -> 点击对应数据包 -> 标头 -> 常规
      • GET 请求参数: 查询参数 (直接在链接中就有)
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 &#xff1a; IN <fs_purhdinfo>-cell_value WITH ."可去掉空格或回车键 REPLACE ALL OCCURRENCES OF R…...

【2024高教社杯全国大学生数学建模竞赛】ABCDEF题 问题分析、模型建立、参考文献及实现代码

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

# VMware 共享文件

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

[UVM]3.核心基类 uvm_object 域的自动化 copy() compare() print() pack unpack

1.核心基类&#xff1a;uvm_object &#xff08;1&#xff09;虚类只能声明&#xff0c;不能例化。 &#xff08;2&#xff09;uvm_object提供的方法 2.域的自动化&#xff08;field automation&#xff09; &#xff08;1&#xff09;简述 &#xff08;2&#xff09;示例 格…...

Java网络编程入门

在现代软件开发中&#xff0c;网络编程是一项不可或缺的技能。Java提供了强大的网络编程支持&#xff0c;使得开发者能够轻松地创建网络应用程序。今天将介绍Java中的网络编程基础&#xff0c;重点讲解Socket和ServerSocket类的使用。 什么是Socket&#xff1f; Socket是网络通…...

前端基础面试题·第三篇——JavaScript(其一)

1.JavaScript数据类型与运算符 数据类型 原始数据类型&#xff1a; 1.Number 2.String 3.Boolean 4.undefined 5.null 6.Symbol 7.bigint 复杂数据类型&#xff1a; 1.Function 2.非函数&#xff1a; Array: 数组 Object: 对象 Date: 日期 RegExp: 正则 Map: 映射 Set: 集合 …...

【机器学习】生成对抗网络(Generative Adversarial Networks, GANs)详解

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

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

Qt 事件处理中 return 的深入解析

Qt 事件处理中 return 的深入解析 在 Qt 事件处理中&#xff0c;return 语句的使用是另一个关键概念&#xff0c;它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别&#xff1a;不同层级的事件处理 方…...