经常会遇到类似下面的这种网站,查个信息得填一堆信息,奇葩的是文本框也不让复制粘贴,而且浏览器还不自动保存,这样每次查询或者超时退出都得重新手动填写一遍。
有没有办法能简化这个过程呢?
办法当然是有的,其中最通用的办法是装个 lastpass 扩展,由它帮你完成表单信息的自动保存与填充,信息也会云存储在他们服务器上,还是挺方便的。
但是如果你担心隐私安全或者想要更加个性化的功能怎么办?一般来说这个时候需要用户自定义脚本来实现了。
Chrome是原生支持加载UserScripts的,只不过它的加载方式是将UserScripts文件转换为一个扩展…… 开发起来略麻烦,不过好处就是稳定可靠。不过这个方案在这里就比较重量级了,不够方便。 所以我决定用TamperMonkey来做这件事儿。 安利一下TamperMonkey扩展,这个相当于Firefox上的Scriptish或GreaseMonkey扩展,相当于一个UserScripts的管理和加载器。挺好使的一个玩意儿,作者貌似是位棒子国的同胞,只不过这货对Chrome的性能影响还是蛮大的。
首先你需要安装好 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 链接。
我们应该经常能遇到上面的 case,每次都要打开链接,然后再返回回来复制密码,再切到下一页面,再粘贴回车,太繁琐啦。
咱们可以看看在 tampermonkey 中如何将这几个交互步骤自动化。
要想在下一页还能拿到上一页密码,只有两种办法,一种是 url 传参,另一种是 Cookie 传递。
这里咱们优先选择 url 传参的方式,基本意思就是找出所有指向百度网盘、360云盘的A标签,然后尝试在A标签后面的文本或A标签当前上级节点里搜索提取码,一旦找到的话,就将其以Hash的方式附加到链接中。
从上一步中的 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 用于一些自动化交互测试以及一些什么秒杀活动自动输入等场合也是极好的,就看大家怎么拿着锤子满世界找钉子了~ :)
[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/