1. 程式人生 > 其它 >Chrome 自動化互動利器:用 tampermonkey 向頁面注入自定義 Javascript

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-zd]{4})/i.exec(txt)&&RegExp.$1;
        if(!code){
            txt=link.parentNode.innerText;
            code=/碼.*?([a-zd]{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-zd]{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/