需求:某網站將自己的下載鏈接給隱藏了,需要自己獲取資源ID再和前綴拼接成資源URL以便下載。
這一部分用手工做很麻煩,所以打算寫個程序來解決。最開始計划寫一個谷歌瀏覽器擴展,但后面突然想到,我還裝了個油猴腳本呢,直接寫個油猴腳本不是更簡單。於是開始了第一個油猴腳本的開發。
油猴腳本基於JS語言的,然而對於JS我只了解一點皮毛。操作網站肯定要了解HTML,但HTML我更是皮毛都不如,只知道一些標簽。沒事,不懂才要學嘛。
首先我們要了解油猴腳本,這部分在網絡上有大量的資源,我就簡單的介紹一下。
// ==UserScript== // @name ScriptName //這個是腳本名 // @namespace http://tampermonkey.net/ //這個第一次開發可以忽略 // @version 0.1 //版本號,在后續更新中會用到 // @description 用於下載對應的png資源 //對腳本的描述 // @author You //作者,不多解釋 // @include *yu3.shop* //適用范圍,可以使用通配符“*”。需要注意的是,如果除了本網址之外還需要適用其他網址,需要新添一條@include // @grant none //第一次開發可以忽略 // ==/UserScript==
(function() { 'use strict'; // Your code here... // 在這兒就可以放自己的JS代碼了。 //放一個alert('Hello World'); 試試? })();
初步了解油猴腳本之后我們分析自己的任務:
那個網頁有多個資源框,對應HTML就是多個表單,表單中有自己需要的資源ID。
所以我要做的事就是:
1. 獲取當前網頁中的所有資源表單
2. 在當前網頁的表單中嵌入一個按鈕
3. 點擊該按鈕,將該按鈕所在表單傳入JS函數中
4. JS獲取表單中的資源ID,並拼接成自己需要的URL
5. 根據該URL下載資源
所以一步步的來,
首先獲取當前網頁中的所有表單:
var obj = document.getElementsByName("download");
第二步:
定義按鈕的HTML代碼
var buttonText = '<input type = "button" value = "Download" style="color: #7ED321" onClick="window.execute(this.form);"/>'; var div = document.createElement("div"); div.innerHTML = buttonText;
這個onClick就是按鈕的點擊方法,這里面有兩個坑我們需要強烈關注。
1. 為什么使用“window.execute(this.form)”而不是execute(this.form)。如果不使用“window.execute(this.form)”而使用“execute(this.form)” 我們會報 “execute() is not defined” 的錯誤。原因在油猴腳本的github項目中有描述,我在此引用一下:
在腳本中定義函數
function abc(){ alert("helloWorld"); }
,注入onclick事件<a id="a" onclick="abc();">HelloWorld</a>
。 爆出函數未定義的錯誤Function is not defined。 在mozillazine了解到Tampermonkey的js腳本是在sandbox中的,在html中訪問不到。 使用下面的例子可以完成這個功能unsafeWindow.abc = function(msg) { alert(msg); }; document.getElementById("a").onclick = "window.abc('helloWorld')";
2. 為什么使用"this.form" 而不是 "this" 傳遞參數。這是因為"this"傳遞的是這個按鈕所在標簽的本身,而我們要的是這個按鈕所在表單。所以使用 "this.form"
第三步:
在所有的資源框中嵌入我們已經寫好的下載按鈕。
這一步很簡單,遍歷就行:
for(var v of obj){ v.appendChild(div.cloneNode(true)); }
這一步需要注意一個坑。為什么我們使用
v.appendChild(div.cloneNode(true));
而非
v.appendChild(div);
這是因為,如果我們直接appendChild "div" 這個元素那么這個按鈕只會在最后一個資源框生效,所以為了保證按鈕能嵌入到所有資源框中,需要使用“div.cloneNode(true)”
接下來寫JS函數,獲取表單中我們需要的資源ID,並拼接成URL
window.execute = function(form){ var path = form.path_image.getAttribute('value');
var url = 'http://www.yu3.shop/browse.php'+path+'&b=21&f=norefer' download(url); }
這一步有一個坑需要注意一下,form.path_image.getAttribute('value')。其中form是傳進來的表單,“path_image”是表單中資源所在標簽的名字 name = "path_image" 表單中無法直接通過“.value”的形式獲取該標簽的值,所以使用“.getAttribute('value')”的方式。
拼接好了url,傳給下載函數:
function download(url){ var eleLink = document.createElement('a'); eleLink.download = url; eleLink.style.display = 'none'; // // 字符內容轉變成blob地址 eleLink.href = url; // // 觸發點擊 document.body.appendChild(eleLink); eleLink.click(); // // 然后移除 document.body.removeChild(eleLink); }
這部分代碼是直接百度的,是我測試的好幾個下載代碼中比較好的一個,沒遇到什么坑,也就不說了。
至此,一個油猴腳本完成了。
總計耗時6個小時左右。其中第二步的那兩個坑至少耗費了我3個小時,最后谷歌到官方文檔才解決,果然遇事不決還是應該多看官方文檔啊。
萬事開頭難,把第二步那兩個坑解決之后后面的還是很輕松的。
挺充實的一天。
最后上完整代碼
// ==UserScript== // @name ScriptName // @namespace http://tampermonkey.net/ // @version 0.1 // @description 用於在yu3.shop代理打開的Illution 網站下載對應的png資源 // @author You // @include *yu3.shop* // @grant none // ==/UserScript== (function() { 'use strict'; // Your code here... var obj = document.getElementsByName("download"); var buttonText = '<input type = "button" value = "Download" style="color: #7ED321" onClick="window.execute(this.form);"/>'; var div = document.createElement("div"); div.innerHTML = buttonText; console.log(obj.length); for(var v of obj){ v.appendChild(div.cloneNode(true)); } // }); window.execute = function(form){ var path = form.path_image.getAttribute('value'); // console.log(path); var name = path.split("/"); var url = 'http://www.yu3.shop/browse.php'+path+'&b=21&f=norefer' download(url); } function download(url){ var eleLink = document.createElement('a'); eleLink.download = url; eleLink.style.display = 'none'; // // 字符內容轉變成blob地址 eleLink.href = url; // // 觸發點擊 document.body.appendChild(eleLink); eleLink.click(); // // 然后移除 document.body.removeChild(eleLink); } })();