我的第一个油猴脚本--微博超话自动签到
简介
由于油猴脚本只用一个JS文档,因而相对于ChromeExtentions比较简单。因此便从油猴脚本开始,首先基本的文件架构是:
// ==UserScript==
// @name New Script
// @namespace Violentmonkey Scripts
// @match http://ju.outofmemory.cn/entry/360333
// @grant none
// ==/UserScript==
其中一些属性的含义:
@name
:
脚本名称
@description
:
脚本功能的描述,显示在脚本标题下面,必填项。
@namespace
:
@namespace
与 @name
这两个属性被作为脚本的唯一标识符,用户脚本管理器根据它们来判断一个脚本是否已安装
@include
, @exclude
, @match
:
描述脚本会在哪些网站上运行。该列表会被解析和展示到脚本的简介页面,并用于脚本的分类。
@supportURL
:
该脚本的技术支持链接(如:错误反馈系统、论坛、电子邮件等),该链接将显示在脚本的反馈页面。
具体的注释信息
脚本简介
第一次编写的脚本是微博超话自动签到,主要借鉴bilibili助手的基本逻辑。本脚本功能实现每日自动签到微博超话。
界面图:
总结:
1.基于$.ajax()对Deferred理解。
主要借鉴$.ajax()引发的对Deferred的总结、回调、使用Promise封装ajax()、Promise入门
ajax()是一种网页中常用的异步操作,其写法有两种
//第一种,传统写法
$.ajax({
url:"/xxx",
type:"get",
success:function(data){//成功调用后的回调函数},
error:function(){//失败调用后的回调函数}
});
//第二种
$.ajax({
url:"/xxx",
type:"get"
}).then(success,fail);//$.ajax()返回的是promise对象
Deffered是一种延迟对象 $.Deffered(),返回Deffered对象
done(fn) 当成功后调用fn
fail(fn) 当失败后调用fn
then(done,fail) done和fail的总写方式
always(fn) 不管成功或失败都执行
resolve和reject执行,便执行done、fail、then、always方法。
resolve(value) 告诉对象执行done回调,value是参数,传入done的回调函数 reject(value) 告诉对象执行fail回调,value是参数.传入fail的回调函数
采用第二种写法可以实现链式编程
const fn=()=>{const p =$.Deferred()
$.ajax({
url:"/xxx",
type:"get"
}).then(
(data)=>{p.resolve(data)},
()=>{p.reject()}
);
return p}
fn().then((data)=>{
//成功后的操作,data是resolve传入的参数
//如果还需要异步执行,可以再定义Deferred对象,以此来实现有顺序的执行
},()=>{
//失败后的操作
})
2.跨域问题
由于JavaScript同源策略的限制,脚本只能读取和所属文档来源相同的窗口和文档。ajax请求时可能会请求不同源的网址。
首先以weibo.com为例说明同源
URL | 结果 | 原因 |
---|---|---|
https://www.weibo.com/dir1/other.html | Success | 同源 |
https://www.weibo.com/dir2/another.html | Success | 同源 |
https://m.weibo.com/1.html | Fail | 主机不同 |
http://www.weibo.com/2.html | Fail | 协议不同 |
https://www.weibo.com:80/3.html | Fail | 端口不同 |
这里用到了两种:
-
document.domain
默认情况下,document.domain存放的是载入文档的服务器的主机名,但不能设置为顶级域名,如www.weibo.com 可以设置为weibo.com 但不能设置为com
具有相同的document.domain就处在同域名的服务器上
-
CORS(跨域资源共享)
CROS是一种跨域访问机制,可以实现Ajax的跨域访问
需配置
//ajax中的配置
xhrFields.withCredentials = true
crossDomain = true
3.添加DOM元素
如果需要向网页中添加按键、css样式等等,就需要添加DOM元素,
如果需要引入CSS样式链接
$(\’head\’).append(\’<link rel=”stylesheet” href=”样式的链接” />\’)
上面的方法主要采取的jquery的方法,也可以用原生JS
const addCSS = (context) => {
const style = document.createElement(\'style\');
style.type = \'text/css\';
style.innerHTML = context;
document.getElementsByTagName(\'head\')[0].appendChild(style);
};//该方法用于添加CSS样式
4.检查类型
一种是通过typeof,可以判断undefined、boolean、string、number、function
可以看到typeof对 对象、数组、null判定为object,有一定的缺陷。
另一种方法用Object.prototype.toString.call判断
可以看到用此方法可以解决之前的混淆
除此之外,脚本也用到了isNaN()判断是否为数字,如果为数字则为false,如果不是数字,则为true。
parseInt(string,radis)将其它类型转换为Int类型,第二个参数为进制
注意: 只有字符串中的第一个数字会被返回。
注意: 开头和结尾的空格是允许的。
注意:如果字符串的第一个字符不能被转换为数字,那么 parseInt() 会返回 NaN。
5.localStorage
window的localStorage
和sessionStorage
储存k/v对的数据,localStorage
中的键值对总是以字符串的形式存储。
localStorage
用于长久保存整个网站数据。
方法:
localStorage.setItem(\'对象名\',\'存储的数据\')
存储
localStorage.getItem(\'对象名\')
读取
localStorage.removeItem(\'对象名\')
移除
localStorage.clear()
移除所有
如果存储的数据是JSON的类型,这可以用JSON.stringify()
和
JSON.parse()
来进行JSON对象和String对象的类型转换
6.一些以后可能用到的方法
const tz_offset = new Date().getTimezoneOffset() + 480;
const ts_s = () => Math.round(ts_ms() / 1000);
const ts_ms = () => Date.now();
const checkNewDay = (ts) => {
// 检查是否为新的一天,以UTC+8为准
const t = new Date(ts);
t.setMinutes(t.getMinutes() + tz_offset);
t.setHours(0, 0, 0, 0);
const d = new Date();
d.setMinutes(t.getMinutes() + tz_offset);
return (d - t > 86400e3);//86400秒为一天的时间
};
const runUntilSucceed = (callback, delay = 0, period = 100) => {
setTimeout(() => {
if (!callback()) runUntilSucceed(callback, period, period);
}, delay);
//如果执行的函数返回值为空,就继续执行,直到callback返回值
};
let API={
processing: 0,
ajax: (settings) => {
if (settings.xhrFields === undefined) settings.xhrFields = {};
settings.xhrFields.withCredentials = true;
jQuery.extend(settings, {
url: (settings.url.substr(0, 2) === \'//\' ? \'\' : \'//weibo.com/\') + settings.url,
method: settings.method || \'GET\',
crossDomain: true,
dataType: settings.dataType || \'json\'
});//jquery.extend用于对象的连接
const p = jQuery.Deferred();
API.runUntilSucceed(() => {
if (API.processing > 8) return false;
++API.processing;
return jQuery.ajax(settings).then((arg1, arg2, arg3) => {
--API.processing;
p.resolve(arg1, arg2, arg3);
return true;
}, (arg1, arg2, arg3) => {
--API.processing;
p.reject(arg1, arg2, arg3);
return true;
});
});