我的第一个油猴脚本--微博超话自动签到

简介

用户脚本是一段代码,它们能够优化您的网页浏览体验。安装之后,有些脚本能为网站添加新的功能,有些能使网站的界面更加易用,有些则能隐藏网站上烦人的部分内容。其中常见的有 油猴插件ChromeExtentions

由于油猴脚本只用一个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 端口不同

这里用到了两种:

  1. document.domain

默认情况下,document.domain存放的是载入文档的服务器的主机名,但不能设置为顶级域名,如www.weibo.com 可以设置为weibo.com 但不能设置为com

 

具有相同的document.domain就处在同域名的服务器上

此处借鉴:通过document.domain实现跨域访问

  1. 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判断数据类型

可以看到typeof对 对象、数组、null判定为object,有一定的缺陷。

另一种方法用Object.prototype.toString.call判断

 

用Object.prototype.toString.call来判断

可以看到用此方法可以解决之前的混淆

除此之外,脚本也用到了isNaN()判断是否为数字,如果为数字则为false,如果不是数字,则为true。

 

parseInt(string,radis)将其它类型转换为Int类型,第二个参数为进制

注意: 只有字符串中的第一个数字会被返回。

注意: 开头和结尾的空格是允许的。

注意:如果字符串的第一个字符不能被转换为数字,那么 parseInt() 会返回 NaN。

5.localStorage

window的localStoragesessionStorage储存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;
              });
          });
           return p;
      }  
}
 
原文地址:https://www.cnblogs.com/deus/p/11516245.html