需求:某网站将自己的下载链接给隐藏了,需要自己获取资源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); } })();