【请抓紧时间上车】实现一个12306的chrom插件

栏目: JavaScript · 发布时间: 6年前

内容简介:源码地址:刚过完年不久,相信大家还能回想到春运时被抢票支配的恐惧。但是本教程并不是教大家如何刷票的。半个月前我帮一个朋友买一张从宿州到上海的火车票,结果。。效果类似下图WTF:

源码地址: github.com/zjians/1230…

起因(吐槽):

刚过完年不久,相信大家还能回想到春运时被抢票支配的恐惧。但是本教程并不是教大家如何刷票的。半个月前我帮一个朋友买一张从宿州到上海的火车票,结果。。效果类似下图WTF:

【请抓紧时间上车】实现一个12306的chrom插件

于是想着买个中间站的票能上车也行,到车上再补票就好了,于是对着车次点了一下,将中间站的名称ctrl+c,ctrl+v一个一个查询有没有余票。一顿操作猛如虎,但是凭着 程序员 的自尊,emm这样不行,操作太傻了。于是周末便撸了这款插件:

【请抓紧时间上车】实现一个12306的chrom插件

【请抓紧时间上车】实现一个12306的chrom插件

嗯嗯,优雅,程序员的自尊又回来了

经过(开发过程):

首先打开chrome开发文档 crxdoc-zh.appspot.com/extensions/…

本来以为要刷很多文档,结果看了20分钟,嗯,感谢自己是个前端,会了。

首先基础工作就是定义一个manifest.json (清单文件),用于定义插件相关的配置。先贴一份本插件的配置文件(各项作用看注释),详细解释请看官方文档:

{     "manifest_version": 2,    "name": "12306",    "version": "1.0",    "description": "查询当前车次各站点的余票",    "author": "https://github.com/zjians/12306",    "page_action": {        "default_icon": {            "16": "assets/icons/icon16.png",            "48": "assets/icons/icon48.png",           "128": "assets/icons/icon128.png"        },        "default_title": "12306上车票"    },     "content_scripts": [{         "matches": ["https://*.12306.cn/*"],         "js": ["js/jquery.min.js","js/main.js"],         "css": ["assets/styles/main.css"],         "run_at": "document_start"    }],    "web_accessible_resources": ["assets/images/*" ]  }复制代码

如果你不想看文档,那么我整理了一份比较全的manifest解释,几乎覆盖了常用的所有设置,可用于快速查询:

{
 "manifest_version": 2,
 /*
   指定您的应用包要求的清单文件格式的版本。从 Chrome 18 开始,开发人员应该指定 2
 */

 "name":"我的应用名称",
 "version":"我的应用版本",

 "default_locale":"zh", // 默认语言
 /*
   对于含有 _locales 目录的应用来说这一属性是必需的,指定_locales中的子目录,包含该应用默认字符串。
   在没有 _locales 目录的应用中该属性不能存在
 */

 "description":"关于应用的描述",

 "icons":{ /*可定义一个或多个, 应用或主题背景的图标*/
   "16":"icon16.png",
   "48":"icon48.png",
   "128": "icon128.png"
 },

 /*
  下面的browser_action或page_action选择某一个使用
  如果插件只对特定页面有效,则使用page_action(页面按钮),(比如抢票插件,只对12306网站有效)
  如果插件对所有页面都有效,则使用browser_action浏览器按钮),(比如截图插件,对所有页面都有效)
 */
 "browser_action": { // 如果有 browser_action, 即在chrome toolbar 的右边添加了一个 icon,
   "default_icon": "test.jpg",
   "default_title": "Google Mail",      // tooltip, 光标停留在 icon 上时显示
   "default_popup": "popup.html"  // 如果有 popup 的页面, 则用户点击图标就会渲染此 HTML 页面
 },

 "page_action":{ // 如果 page_action 并不应用在当前页面, icon会显示灰色
   "default_icon": {
     "19": "images/icon19.png",
     "38": "images/icon38.png"
   },
   "default_title": "Google Mail",
   "default_popup": "popup.html"
 },

 //可选
 "author":"开发者",
 "automation":"",


 "background":{
   "scripts":["background.js"],
   "page": "background.html",
   "persistent":false
 },
 /*
  后台网页
  1.应用通常需要有一个长时间运行的脚本来管理一些任务或状态,而后台网页就是为这一目的而设立。
  通常情况下,后台页面不需要任何 HTML 标记,这种情况下后台页面可以单独使用 JavaScript文件实现。
  后台页面将由应用系统生成,包含 scripts 属性中列出的每一个文件。
  2.page:如果您需要在您的后台页面中指定 HTML,您可以改用 page 属性:
  3.persistent:应用和应用通常需要长时间运行的脚本来管理某些任务或状态,这就是事件页面的作用。
  事件页面只在需要时加载,当事件页面不活动时就会卸载,以便释放内存和其他系统资源。
  如何得到事件页面 就是设置一个"persistent"键,如果没有设置,你将得到一个普通的后台页面。
 */


 "content_scripts": [{
   "matches": ["https://*.domain.com/*"], // 匹配的地址网页
   "exclude_matches":[],
   "js": ["jquery.js","yourScript.js"], // 内容脚本
   "css": ["yourStyles.css"], // 在页面上添加的css样式
   "run_at":"document_idle",
   "all_frames": true //该匹配下面的所有窗口
 },{ // 可以针对不同的规则插入不同的内容
   "matches": ["*://*/*.png", "*://*/*.jpg", "*://*/*.gif", "*://*/*.bmp"],
   "js": ["js/show-image-content-size.js"]
 }],
 /*
   内容脚本: 其实就是向你想要的网页中插入一个脚本代码,执行你想要做的事情
            内容脚本是在网页的上下文中运行的 JavaScript 文件,
            它们可以通过标准的文档对象模型(DOM)来获取浏览器访问的网页详情,或者作出更改。
   
   1.run_at 可选。
   控制 js 中的 JavaScript 文件何时插入,
   可以为 "document_start"、
   "document_end" 或 "document_idle",默认为 "document_idle"。 

      1.1如果是 "document_start",这些文件将在 css 中指定的文件之后,但是在所有其他 DOM 构造或脚本运行之前插入。 

      1.2.如果是 "document_end",文件将在 DOM 完成之后立即插入,但是在加载子资源(如图像与框架)之前插入。 

      1.3.如果是 "document_idle",浏览器将在 "document_end" 和刚发生 window.onload 事件这两个时刻之间选择合适的时候插入,
      具体的插入时间取决于文档的复杂程度以及加载文档所花的时间,并且浏览器会尽可能地为加快页面加载速度而优化。 
    
   2.all_frames 可选。
   控制内容脚本运行在匹配页面的所有框架中还是仅在顶层框架中。 默认为 false,意味着仅在顶层框架中运行
 */

"web_accessible_resources": [ // 普通页面能够直接访问的插件资源列表,如果不设置是无法直接访问的
   "images/*.png",
   "style/double-rainbow.css",
   "script/double-rainbow.js",
   "script/main.js",
   "templates/*"
 ],

 "update_url": "你的插件在chrome商店的地址", // 如果你使用 Chrome 开发者信息中心发布的扩展程序,可忽略这一项
 // 如果你想从自己的服务器上更新插件,则需要指定update_url,指向你的服务器地址。

"homepage_url": "https://www.xxx.com", // 插件的主页

"permissions":[
   "tabs", // 如果扩展使用chrome.tabs或chrome.windows模块,则添加此项
   "bookmarks", // 使用chrome.bookmarks模块来创建、组织和管理书签
   "http://www.blogger.com/",    
   "http://*.google.com/",    
   "unlimitedStorage", // 提供了一个无限的HTML5配额来存储客户端数据,如数据库和本地存储文件。没有这个权限,扩展仅限于5 MB的本地存储
   "history" // 历史记录的使用权限  chrome.history 
   "notifications",// 提示
   "cookies",// 如果扩展程序使用chrome.cookies模块,则添加此项
 ],
 /*  
   扩展或app将使用的一组权限。每个权限是一列已知字符串列表中的一个,
   如geolocatioin或者一个匹配模式,来指定可以访问的一个或者多个主机。
   权限可以帮助限定危险,如果你的扩展或者app被攻击。
   有些权限在安装之前,会告知用户
*/

key:'',
/**开发时为扩展指定的唯一标识值。
  注意:通常您并不需要直接使用这个值,而是在您的代码中使用相对路径或者chrome.extension.getURL()得到的绝对路径。
  这个值并不是开发时显式指定的,而是Chrome在安装.crx时辅助生成的。(开发时可以通过上传扩展或者手工打包生成crx文件)。 
  安装完crx,在Chrome的用户数据目录下的Default/Extensions/<extensionId>/<versionString>/manifest.json文件中,您可以看到这个扩展的key。
**/

"commands": {
     // commands API 用来添加快捷键
     // 需要在 background page 上添加监听器绑定 handler
   "toggle-feature-foo": {
     "suggested_key": {
       "default": "Ctrl+Shift+Y",
       "mac": "Command+Shift+Y"
     },
     "description": "Toggle feature foo",
     "global": true
       // 当 chrome 没有 focus 时也可以生效的快捷键
       // 仅限 Ctrl+Shift+[0..9]
   },
   "_execute_browser_action": {
     "suggested_key": {
       "windows": "Ctrl+Shift+Y",
       "mac": "Command+Shift+Y",
       "chromeos": "Ctrl+Shift+U",
       "linux": "Ctrl+Shift+J"
     }
   },
   "_execute_page_action": {
     "suggested_key": {
       "default": "Ctrl+Shift+E",
       "windows": "Alt+Shift+P",
       "mac": "Alt+Shift+P"
     }
   },
   ...
 },
 "content_capabilities": ...,
 "optional_permissions": ["tabs"], // 其他需要的 permission, 在使用 chrome.permissions API 时用到, 并非安装插件时需要

 "short_name": "Short Name", // 插件名字简写

"storage": {//  使用 storage.managed api 的话, 需要一个 schema 文件指定存储字段类型等, 类似定义数据库表的 column
   "managed_schema": "schema.json"
 },
......
}复制代码

嗯,配置完以后,就可以在页面中插入自己的脚本了,于是就可以为所欲为了。

这里说下开发中遇到的三个问题:

1. 获取站点的缩写码,比如【北京北】的站点码为VAP,因为请求数据的时候传过去的参数,使用的不是站点中文名称,而是站点码。

于是我在网站中发现了这么一个变量:station_names,如下图所示:

【请抓紧时间上车】实现一个12306的chrom插件

      很显然解析这个变量就可以获得站点对应的站点码了, 但是chrome插件和原始网页是两个相互分开的运行环境,也就是说我在插件的脚本中无法获取页面脚本中的变量 。但是插件是可以获取页面的dom内容的,于是把station_names挂到dom上,然后在插件中获取dom上的属性。这样便通过dom获取到了页面脚本中的变量值,代码如下:

const script = document.createElement('script');script.type = 'text/javascript';script.innerHTML = "document.body.setAttribute('data-station-name', station_names);";document.head.appendChild(script);document.head.removeChild(script);const station_names = document.body.getAttribute('data-station-name');复制代码

2. 解析12306返回的数据

你可能会问,解析数据不是很简单的吗?我也是这么认为,但是直到我看到了他的返回:

【请抓紧时间上车】实现一个12306的chrom插件

自己解析肯定是不现实了,那么就找找网站的脚本是如何解析这个数据的吧,于是我找到了这个函数,就是他了:

【请抓紧时间上车】实现一个12306的chrom插件

经过上面函数的处理,得到了我想要的结果对象: 【请抓紧时间上车】实现一个12306的chrom插件

完美!

3. 本来以为可以开心的玩耍了,但是第二天一试,居然请求不到数据了。。

查看请求地址才发现,原来查询地址是每天都变的,好在请求失败以后,会返回可用的地址,于是在插件运行时,检测一下目前可用的请求地址:

let queryUrl = 'leftTicket/queryZ' // 请求地址$.ajax({    type: 'GET',    url: `https://kyfw.12306.cn/otn/${queryUrl}?leftTicketDTO.train_date=2019-02-20&leftTicketDTO.from_station=VNP&leftTicketDTO.to_station=NKH&purpose_codes=ADULT`,    error: function (res) { // 如果失败了,会返回可用的地址      queryUrl = res.responseJSON.c_url    }  })复制代码

ok!完成。

结束语:

1.如果觉得有用,请反手给个 star 鼓励一下

2.请上车后补票 :joy:

感谢观看

【请抓紧时间上车】实现一个12306的chrom插件


以上所述就是小编给大家介绍的《【请抓紧时间上车】实现一个12306的chrom插件》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Black Box Society

The Black Box Society

Frank Pasquale / Harvard University Press / 2015-1-5 / USD 35.00

Every day, corporations are connecting the dots about our personal behavior—silently scrutinizing clues left behind by our work habits and Internet use. The data compiled and portraits created are inc......一起来看看 《The Black Box Society》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具