Chrome 自动化交互利器:用 tampermonkey 向页面注入自定义 Javascript

1、背景

经常会遇到类似下面的这种网站,查个信息得填一堆信息,奇葩的是文本框也不让复制粘贴,而且浏览器还不自动保存,这样每次查询或者超时退出都得重新手动填写一遍。

有没有办法能简化这个过程呢?

办法当然是有的,其中最通用的办法是装个 lastpass 扩展,由它帮你完成表单信息的自动保存与填充,信息也会云存储在他们服务器上,还是挺方便的。

但是如果你担心隐私安全或者想要更加个性化的功能怎么办?一般来说这个时候需要用户自定义脚本来实现了。

2、tampermonkey 简介

Chrome是原生支持加载UserScripts的,只不过它的加载方式是将UserScripts文件转换为一个扩展…… 开发起来略麻烦,不过好处就是稳定可靠。不过这个方案在这里就比较重量级了,不够方便。 所以我决定用TamperMonkey来做这件事儿。 安利一下TamperMonkey扩展,这个相当于Firefox上的Scriptish或GreaseMonkey扩展,相当于一个UserScripts的管理和加载器。挺好使的一个玩意儿,作者貌似是位棒子国的同胞,只不过这货对Chrome的性能影响还是蛮大的。

3、用 tampermonkey 实现自动化交互

首先你需要安装好 Chrome 以及 tampermonkey 插件,然后在你需要自动交互的网站上点击扩展图标,这样你就可以开始写你的交互逻辑代码了:

上面是一个很通用的模板,如果你看不懂的话也许需要去看下UserScripts的格式…… 这里先把 @name  和 @match  改掉,一个是名字,一个是匹配的网址。名字随便取,@match  改为 http://www.ooxx.com/*。 然后在最下面开始写代码。

比如文初开头的完整代码如下:

// ==UserScript==
// @name         ooxx网站
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://www.ooxx.com/wsyw/wscx/gjjcx-logineoor.jsp?id=2
// @grant        none
// ==/UserScript==
/* jshint -W097 */
'use strict';

// Your code here...


(function () {
    document.getElementsByTagName("option")[1].selected = true;
    document.form1.bh.value = "ID:NO";
    document.form1.mm.value = "passwd";

    //function post(path, params, method) {
    //  method = method || "post"; // Set method to post by default if not specified.
    //
    //  // The rest of this code assumes you are not using a library.
    //  // It can be made less wordy if you use one.
    //  var form = document.createElement("form");
    //
    //  form.setAttribute("method", method);
    //  form.setAttribute("action", path);
    //
    //  for (var key in params) {
    //      if (params.hasOwnProperty(key)) {
    //          var hiddenField = document.createElement("input");
    //          //hiddenField.setAttribute("type", "hidden");
    //          hiddenField.setAttribute("name", key);
    //          hiddenField.setAttribute("value", params[key]);
    //
    //          form.appendChild(hiddenField);
    //      }
    //  }
    //
    //  var iframe = document.createElement("iframe");
    //  //document.body.appendChild(iframe);
    //  //document.querySelector("iframe").contentWindow.document.childNodes[0].appendChild(form);
    //  //form.submit();
    //
    //}
    //
    //post('http://lab.ocrking.com/do.html', {
    //  url : 'http://www.ooxx.com/wsyw/servlet/PicCheckCode1',
    //  service : 'OcrKingForCaptcha',
    //  language : "eng",
    //  charset : "7",
    //  outputFormat : "",
    //  email : ""
    //});
})();

这样当你每次打开 http://www.ooxx.com/wsyw/wscx/gjjcx-logineoor.jsp?id=2 时,下拉列表会被选择好,同时各个表单域的值也会填写成预设值,如果验证码也破解成功则可以直接模拟点击事件提交表单,文章开头提到的繁琐流程至此一气呵成十分方便!

关于最后一个验证码的破解有两种思路:

  • 利用Canvas进行验证码识别,属于纯 js 破解,需要针对性的分析验证码的色彩与位置分布特点等,兼容性不好
  • 利用云服务来破解,不过这种需要注意 Ajax 跨域问题,推荐使用 js 构造iframe,然后嵌套 form 表单提交 post 的方式来请求服务

这两点思路可以参考文末的 Refer 链接。

4、个性化需求:目标页自动输入百度网盘密码

我们应该经常能遇到上面的 case,每次都要打开链接,然后再返回回来复制密码,再切到下一页面,再粘贴回车,太繁琐啦。

咱们可以看看在 tampermonkey 中如何将这几个交互步骤自动化。

4.1 给跳转 url 带上尾巴

要想在下一页还能拿到上一页密码,只有两种办法,一种是 url 传参,另一种是 Cookie 传递。

这里咱们优先选择 url 传参的方式,基本意思就是找出所有指向百度网盘、360云盘的A标签,然后尝试在A标签后面的文本或A标签当前上级节点里搜索提取码,一旦找到的话,就将其以Hash的方式附加到链接中。

4.2 提取密码并模拟点击

从上一步中的 URL Hash 中截取密码并赋值给密码框,最后模拟点击事件即可。

代码最终如下:

// ==UserScript==
// @name         zdfans
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://www.zdfans.com/*
// @grant        none
// ==/UserScript==
/* jshint -W097 */
'use strict';

// Your code here...
// 4.1
document.querySelectorAll("a[href*='pan.baidu.com'], a[href*='yunpan.cn']").forEach(
    function(link){
        var txt=link.nextSibling&&link.nextSibling.nodeValue; 
        var code=/码.*?([a-z\d]{4})/i.exec(txt)&&RegExp.$1;
        if(!code){
            txt=link.parentNode.innerText;
            code=/码.*?([a-z\d]{4})/i.exec(txt)&&RegExp.$1;
        }
        if(code){ 
            var href=link.getAttribute("href");
            link.setAttribute("href", href+"#"+code);
        }
    }
);


// 4.2
var pathname=self.location.pathname;

!function(){
    if(pathname.indexOf("/share/")!==-1&&document.getElementById("accessCode")){
        var code=self.location.hash.slice(1,5);
        if(/[a-z\d]{4}/i.exec(code)){
            document.getElementById("accessCode").value=code;
            document.getElementById("submitBtn").click();
        }}
}();

需要说明的是,虽然效果很好很赞,但最大的问题是:需要跑UserScripts。所以一般在常去的资源站上用用就好了,没必要把脚本跑到每个网站上,毕竟那是极浪费性能的事儿~

上面我只匹配了zdfans网站,但其实只要改@match ,这段脚本可以匹配大多数使用网盘共享的网站。

最后感谢 木魚 童鞋提供的思路与分享,其实引申开来,TamperMonkey 用于一些自动化交互测试以及一些什么秒杀活动自动输入等场合也是极好的,就看大家怎么拿着锤子满世界找钉子了~ :)

Refer:

[1] 技术贴:使用UserScript自动通过百度网盘/360云盘提取码

http://blog.fishlee.net/2016/03/09/using-contentscripts-to-pass-access-code/

[2] Javascript : get <img> src and set as variable?

http://stackoverflow.com/questions/7882356/javascript-get-img-src-and-set-as-variable

[3] 使用Canvas进行验证码识别

http://www.cnblogs.com/ziyunfei/archive/2012/10/05/2710349.html

[4] JS破解乌云验证码

http://zone.wooyun.org/content/18101

[5] OCR 在线识别验证码

http://lab.ocrking.com/

[6] UserScript:自动提取XClient上的下载链和提取码

http://blog.fishlee.net/2016/03/18/userscipts-pass-xclient-downloadlink/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨龙飞前端

react的一些思考

在做好第一个需求之后,我接到了一个react写的产品,这让我异常的兴奋,终于能写react了

923
来自专栏华仔的技术笔记

React Native 初探

3746
来自专栏恰童鞋骚年

微信小程序开发初探

  (1)一切以用户价值为依归→用户是微信的核心,所以微信中没有很多与客户无关的功能,比如QQ中的乱七八糟一系列东西。

4583
来自专栏快乐八哥

Angular企业级开发(3)-Angular MVC实现

1.MVC介绍 Model-View-Controller 在20世纪80年代为程序语言Smalltalk发明的一种软件架构。MVC模式的目的是实现一种动态的...

2289
来自专栏何俊林

Android性能全面分析与优化方案研究

性能优化是一个持续的过程,要多种手段,一点一点优化,一般是优化影响比较大头的,再逐步优化小头的,今天是手机迅雷Android高级工程师做的性能分析及优化方案分享...

6298
来自专栏hightopo

快速开发基于 HTML5 网络拓扑图应用1

2932
来自专栏前端架构与工程

Typescript+WebGL+Webpack开发环境搭建

目前Web实现矢量渲染的主流技术包括SVG、VML和WebGL。相对而言,VML是一种较古老的技术,虽然未成为W3C标准,但被早期的IE浏览器(IE9以下)和微...

2343
来自专栏大前端开发

微信小程序填坑-Android真机环境下的bluebird.js

今天,有朋友反映说,我的微信小程序的例子在andriod真机环境下运行出错,研究调试了半天,发现原来是使用的bluebird.js(Promise实现库)导致的...

813
来自专栏繁花云

11.14学习总结

解决方案:mysqli_set_charset($conn,utf8)

840
来自专栏.net core新时代

我的前端学习历程

  很难想象一个半年前还在做后台开发,对前端知之甚少的我,现在也可以从事前端开发了。这半年的学习过程将会是我人生一笔宝贵的财富,这让我想到一句话“在成长的道路上...

2436

扫码关注云+社区

领取腾讯云代金券