# chromePlugin12306 **Repository Path**: leolee18/chrome-plugin12306 ## Basic Information - **Project Name**: chromePlugin12306 - **Description**: chrome 插件,用于自动化12306购票功能,方便用户购买火车票。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 3 - **Created**: 2024-01-20 - **Last Updated**: 2025-05-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # chrome插件12306抢票 ## 12306 订票助手 – 火车票自动订票 Chrome 扩展 ### 快过年了,相信大家还能回想到往年春运时抢票的恐惧。要是热门线路,你想要买票简直就是难上加难。如果想要购票只能使用抢票软件,但是这些软件不仅需要购买加速包、找人助力,甚至可能导致隐私泄露,到最后抢票速度可能还不如自己手动来得快。于是周末便撸了这款插件:教大家如开发一个chrome插件,实现刷票购买、提交、确认一气呵成。 ![alt 效果图](img/set.png "效果图") ## 订票助手实现的功能 ```text 1、自动刷票,自动到购买界面。可以设置指定车次、席别固定为硬座、硬卧、二等座。 2、自动选定乘车人。 3、自动提交订单。 4、自动确认。 5、设置界面,可以设置车次、自动步骤、乘车人序号。 ``` ## 实现思路 ```js 通过监听网页加载完成和车票查询接口响应,触发对车票预订按钮的遍历。遍历到符合要求的预订按钮后,模拟点击预订按钮。如果没查到预订按钮,模拟点击查询按钮,则继续监听。如此循环直到可以预订。在购买页面,监听页面加载完成,触发对乘车人勾选。后面提交订单,由于12306对自动提交的订单,弹出的确认加了延时。所以我循环监听确认按钮的可用样式。可用后,自动提交确认。 设置界面。通过在车次票查询界面,注入一块设置框,实现用户设置车次、自动步骤、乘车人序号。车次是通过遍历界面上的车次表格来拿到的。为了方便下次打开使用,将设置信息保存在本地。 ``` ## 新建配置文件 manifest.json ```json //首先基础工作就是定义一个manifest.json (清单文件),用于定义插件相关的配置。 { "manifest_version": 3, //指定您的应用包要求的清单文件格式的版本。 "name": "Chrome抢票", "version": "1.0", "description": "chrome抢票扩展,仅供技术交流", "action": { //如果有 action, 即在chrome toolbar 的右边添加了一个 icon "default_icon": { "19":"img/icon.png" } }, "icons":{ //可定义一个或多个, 应用或主题背景的图标 "16": "img/icon.png", "48": "img/icon.png" }, "permissions": [//扩展使用的一些权限 "webRequest", "tabs" ], "host_permissions": [//主机权限v3版本,从permissions从分离出来了 "" ], "background": {//后台网页,应用通常需要有一个长时间运行的脚本来管理一些任务或状态,而后台网页就是为这一目的而设立。 "service_worker": "background.js" }, "content_scripts": [ { "matches": ["https://kyfw.12306.cn/otn/leftTicket/init*"],// 匹配的地址网页 "js": ["js/data.js","js/scriptList.js"],// 内容脚本 "css":["css/index.css"]// 在页面上添加的css样式 }, { "matches": ["https://kyfw.12306.cn/otn/confirmPassenger/initDc"], "js": ["js/data.js","js/scriptSubmit.js"] } ] } ``` ## 12306 查询界面开发 ### data.js 保存设置的数据 ```js var mListAll = []; // 用户车次列表 var mAutos = []; // 自动提交的一些设置 var mInputs = []; // 用户输入乘车人序号 ``` ### background.js 查询接口监听 ```js var mBool = false; //限制加载完成后的口返回,避免重复加载数据 // 监听请求 chrome.webRequest.onHeadersReceived.addListener(function (details) { // 判断是否是查询接口 if(details.url.indexOf('https://kyfw.12306.cn/otn/leftTicket/queryE') !== -1){ if(mBool){ // 发消息到content_scripts界面 chrome.tabs.query({active:true,currentWindow:true},function(tabs){ chrome.tabs.sendMessage(tabs[0].id,{name:'list',content:details.url}); }); } } return {responseHeaders: details.responseHeaders}; }, { urls: [ "",// 监听所有请求 ] }, ['responseHeaders'] ); // 监听界面加载完成消息 chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){ if(message.name == 'load'){ mBool = true; } }); ``` ### scriptList.js 查询界面注入的开发 ```js //筛选购买方法 function startButtonClick() { // 所有可用的,预定按钮 var buttons = document.getElementsByClassName('btn72'); // 车次席别选择 var gt2dz = document.getElementById('cc_seat_type_O_check'); gt2dz?.click(); // 高铁二等座 var kyw = document.getElementById('cc_seat_type_3_check'); kyw?.click(); // 硬卧 var kyz = document.getElementById('cc_seat_type_1_check'); kyz?.click(); // 硬座 var mBool = false; for (let index = 0; index < buttons.length; index++) { var button = buttons[index]; if (button!='') { var mHCNumber = button.parentNode.parentNode.childNodes[0].childNodes[0].childNodes[0].childNodes[0].childNodes[0]?.innerHTML; if(mListAll.length == 0 || (mListAll.length > 0 && mListAll.includes(mHCNumber))){ // 自动触发预定按钮,去购买页面 if (mAutos.includes('zdcx')) { button?.click(); mBool = true; } break; } } } if(!mBool){ //延时1妙刷新 setTimeout(function() { // window.location.reload(); // 刷新页面,会慢一些 // 触发查询按钮,刷新 var inquireB = document.getElementById('query_ticket'); if (mAutos.includes('zdcx')) { inquireB?.click(); } }, 1000); } } window.onload = function() { // 去筛选购买 startButtonClick(); //发消息给后台网页,监听接口 chrome.runtime.sendMessage({ name: 'load', content:'' }); } // 监听后台网页口加载完成,也就是点查询按钮时,触发筛选购买。 chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { if (message.name === "list") { setTimeout(function() { startButtonClick(); } ,50); } }); ``` #### 设置功能 ```js window.onload = function() { //设置界面 mIntLoad();//获取本地缓存 uiBody();//设置界面注入 //…… } // 获取本地缓存数据实现 function mIntLoad() { var mAll = localStorage.getItem('mListAll'); var mAut = localStorage.getItem('mAutos'); var mInp = localStorage.getItem('mInputs'); if(mAll){ mListAll = JSON.parse(mAll); }else{ mListAll = []; } if(mAut){ mAutos = JSON.parse(mAut); }else{ mAutos = []; } if(mInp){ mInputs = JSON.parse(mInp); }else{ mInputs = []; } } //设置界面注入实现,监听方法,本地存储等。大家看的懂,我就不废话了。 function uiBody() { var tableList = document.getElementById('queryLeftTable'); var rowCount = tableList.rows.length; var mCCDiv = document.createElement("div"); mCCDiv.className = "plugin-one"; for (let index = 0; index < rowCount; index++) { var firstCellRowSpan = tableList.rows[index].cells.length; if(firstCellRowSpan > 1){ var mCZDom = tableList.rows[index].cells[0].childNodes[0]; var mCZNumber = mCZDom.childNodes[0].childNodes[0].childNodes[0]?.innerHTML; mCCDiv.appendChild(crateCheck(mCZNumber,mCZNumber,index,handleCheckboxChange)); } } ………… mPluDiv.appendChild(mAllDome); var body = document.body; body.appendChild(mPluDiv); } ``` ## 12306 订票界面开发 ```js // 界面加载完成 window.onload = function() { mIntLoad();//获取本地用户设置的数据。 sendButton();//界面功能注入 } //界面功能注入 function sendButton() { //设置乘车用户 if(Array.isArray(mInputs)){ mInputs.forEach((item)=>{ var label = document.getElementsByClassName('check')[item]; label.click(); }) }else{ var label = document.getElementsByClassName('check')[0]; label.click(); } //触发提交按钮 var button = document.getElementById('submitOrder_id'); if (mAutos.includes('zdtj')) { button.click(); } // 监听界面弹框,有确认按钮时自动提交 loopSubmit(); } //确认按钮自动提交实现,由于12306对自动提交后的确认按钮进行了限制,所以需要循环监听确认按钮的className变化。 function loopSubmit() { var sendB = document.getElementById('qr_submit_id'); if(sendB){ if(sendB.className == 'btn92s'){ if (mAutos.includes('zdqr')) { sendB.click(); } }else{ sendB.className = 'btn92s'; setTimeout(loopSubmit, 500); } }else{ setTimeout(loopSubmit, 30); } } ``` ## 安装 ```text 1、打开google chrome的菜单(三条线图标) 2、点击”更多工具“ > ”扩展程序“ 3、打开开发者模式 4、点击”加载已解压的扩展程序“,选择文件目录 5、点击”启用“即可使用 ```