油猴(篡改猴)学习记录

news2025/2/24 6:31:57

第一个Hello World

  • 注意点:默认只匹配了http网站,如果需要https网站,需要自己添加@match https://*/*
  • 代码如下
    • 这样子访问任意网站就可以输出Hello World
// ==UserScript==
// @name         第一个脚本
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://*/*
// @match        https://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    console.log("你好,世界")
})();

重要了解

@grant

  • @grant 用于将 GM_*GM.* 函数、 unsafeWindow 对象和一些强大的 window 函数列入白名单。

    // @grant GM_setValue
    // @grant GM_getValue
    // @grant GM.setValue
    // @grant GM.getValue
    // @grant GM_setClipboard
    // @grant unsafeWindow
    // @grant window.close
    // @grant window.focus
    // @grant window.onurlchange
    
  • 由于关闭和聚焦选项卡是一个强大的功能,因此也需要将其添加到 @grant 语句中。如果 @grant 后跟 none ,则禁用沙盒。在此模式下,没有 GM_* 函数,但 GM_info 属性将可用。

// @grant none
  • 如果没有给定 @grant 标记,则假定为空列表。但是,这与使用 none 不同。
  • 说白了就是你不设置@grant标记,你就不能使用GM_addElement等等GM_的函数

@match

  • 主要运行脚本的网站
  • 如果需要在全部链接上运行,就只需添加如下
@match *://*/*
  • 需要注意的是@match规则是匹配多少次,就运行多少次编写的脚本文件

  • 下面的例子就可以很好的说明match几次就执行多少次脚本
// @match        http://www.yinghuavideo.com/v/*
// @match        https://tup.yinghuavideo.com/*
// 输出查看
console.log(window.location.href)

//输出如下内容
	//第一次输出
http://www.yinghuavideo.com/v/5971-9.html
	//第二次输出
https://tup.yinghuavideo.com/?vid=https://cdn18.vipyz-cdn3.com/20230902/15434_377b32aa/index.m3u8$mp4

@require

  • 油猴给我们提供了一个@require属性给我们来引用用户脚本,并且油猴给我们提供了md5,sha256等校验方法来校验引用的脚本是否正确,例如下面这样:

    // @require      https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js#md5=xxxx
    
  • 如果md5不正确,console中则会显示下面的内容

  • 也支持 SHA-256MD5 哈希
  • 如果给出多个哈希(用逗号或分号分隔),则当前支持的最后一个哈希值由 Tampermonkey 使用。所有哈希都需要以十六进制或 Base64 格式编码。
// @require              https://code.jquery.com/jquery-2.1.1.min.js#md5=45eef...
// @require              https://code.jquery.com/jquery-2.1.2.min.js#md5-ac56d...,sha256-6e789...
// @require              https://code.jquery.com/jquery-3.6.0.min.js#sha256-/xUj+3OJU...ogEvDej/m4=

@resource

  • 一些可以通过GM_getResourceTextGM_getResourceURL访问的静态资源。 后面写名值对,名是资源的名称,值是相应的url,中间以空格隔开(所以名字中不能包含空格😄),可多次定义

    // @resource logo https://my.cdn.com/logo.png
    // @resource text https://my.cdn.com/some-text.txt
    
  • 然后就可以使用getResourceText引入了

// ==UserScript==
// @name         TEST调试专用
// @namespace    https://blog.csdn.net/jx520
// @version      0.1
// @author       jerryjin
// @match        *://*/*
// @grant        GM_getResourceText
// @resource myTxt https://cdn.jsdelivr.net/gh/wandou-cc/blog-ui@20230314_v1/index.css
// ==/UserScript==
(async function() {
    'use strict';
    let txt = GM_getResourceText('myTxt');
    console.log(txt);
    let json = JSON.parse(txt);
    console.log(json);
})();

@GM_addElement

  • 可以用来添加script,css,或者为指定的DOM添加对应属性或元素

添加script-1

  • head下添加
GM_addElement('script',{
	textContent: " window.foo = 'bar' "
})

添加script-指向url

  • head下添加
GM_addElement('script',{
    src:'https://example.com/script.js',
    type:'text/javascript',
})

添加style和css的link

  • 下面这个操作就不解释什么意思了,应该都看得懂
GM_addElement(document.getElementsByTagName('div')[0], 'img', {
  src: 'https://example.com/image.png'
});

GM_addElement(shadowDOM, 'style', {
  textContent: 'div { color: black; };'
});
  • style应该这么用
  GM_addElement("style", {
    textContent: `
    body #git-hub-box-bt {
      background: #242429 !important;
      border-color: #555666 !important
  }`,
  });

@GM_addStyle

  • 传入的参数就是css样式,css样式这么写,这里就可以写,用模板语法会很方便,和css书写一样,下面例子就是模板语法添加的样式信息
  GM_addStyle(
    `
      .abc{
        position:absolute;
        left:0;
        right:0;
      }
      #id{
        background:red,
      }
      body{
        padding-left:10px;
        background:blue;
      }
    `
  )

@GM_setValue

  • GM_setValue(key,value)
GM_setValue("someKey", "someData");
await GM.setValue("otherKey", "otherData");
  • 暂时不明白为什么需要await

@GM_getValue

  • GM_getValue(key,defaultValue)
    • key不存在的时候,则返回默认值
const someKey = GM_getValue("someKey", null);
const otherKey = await GM.getValue("otherKey", null);

@GM_deleteValue

  • GM_deleteValue("someKey")
  • 从用户脚本的存储中删除对应的key
GM_deleteValue("someKey");
await GM.deleteValue("otherKey");

@GM_listValues

  • GM_listValues 函数返回所有存储数据的key列表。
const keys = GM_listValues();
const asyncKeys = await GM.listValues();

//刚刚设置了
//GM_setValue('sexInfo',JSON.stringify({
//  name:'李白',
//  age:18,
//  sex:'男',
//}))

//输出 数组: ['sexInfo']
console.log(GM_listValues());

unsafeWindow

  • 作用:允许脚本可以完整访问原始页面,包括原始页面的脚本和变量。
  • 简单理解为自己脚本里面的window是独立于外面的,无法访问到原始网页的window对象里面的信息
  • 注意unsafeWindowwindow是不一样的
  • 比如有一个网页,代码如下
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    var from4 = '我是来自网页4.html的内容';
  </script>
</body>
</html>
  • 然后我们@grant引入unsafeWindow
//油猴脚本内容如下

console.log(window.from4,unsafeWindow.from4);
//网页输出结果为
// undefined '我是来自网页4.html的内容'
  • 可以看到,我们在代码直接访问window是获取不到的,需要使用unsafeWindow

@GM_registerMenuCommand

  • GM_registerMenuCommand(name, callback, accessKey);

    • name: 包含要为菜单项显示的文本的字符串。

    • callback: 回调:选择菜单项时要调用的函数。该函数将传递单个参数,即当前活动的选项卡。从Tampermonkey 4.14开始,MouseEvent或KeyboardEvent作为函数参数传递。

    • accessKey: 访问键:菜单项的可选访问键。这可用于为菜单项创建快捷方式。例如,如果访问键为“s”,则用户可以在打开Tampermonkey的弹出菜单时按“s”来选择菜单项。

  • 该函数返回可用于注销命令的菜单项 ID

    • 也就是通过GM_unregisterMenuCommand(menuCmdId)
const menu_command_id = GM_registerMenuCommand("Show Alert", function(event: MouseEvent | KeyboardEvent) {
  alert("Menu item selected");
}, "a");
  • 如果需要通过alt或者ctrl这种组合键的,就需要如下的做法了
(function () {
  "use strict";
  const userSelfKey = "h"; //结合后面,设置用户按下alt + h 完成回调
  //点击后执行的回调
  const callback =  () => {
    console.log("点击执行回调");
  };
  GM_registerMenuCommand(`是否启动(Alt+${userSelfKey})`,);
  document.addEventListener("keydown", (e) => {
    if ((e.altKey, e.key.toLowerCase() === userSelfKey)) {
      callback();
    }
  });
})();

@run-at

  • 说通俗点就是代码什么时候注入(因为注入时机不同,可以对网页的操作量也不同)
  • 官方文档 @地址
  • 就如同作者说的,想要替换setInterval函数,达到时间加速,就必须在调用之前被替换,所以就应该更改run-at的值
首先来介绍一下时间加速的原理.一般情况下,都是使用setInterval来做定时器,我们只要把这个定时器的时间缩短,比如之前是1s触发一次,现在变成500ms触发一次,那么就相当于时间缩短了一倍.

怎么缩短呢?我们可以劫持setInterval这个函数,传入值为1000,我们把他变为500.代码类似下面这样:

let hookSetInterval=window.setInterval;//将系统提供的setInterval保存
window.setInterval=function(a,b){//将系统的setInterval替换为我们自己的
    return hookSetInterval(a,b/2);//经过处理后再调用系统的setInterval
}

@GM_xmlhttpRequest

  • 和自带的ajax请求和fetch更强大,支持跨域这个GM_xmlHttpRequest
  • 重要提示:如果要使用此方法,请同时查看有关 @connect 的文档。
// ==UserScript==
// @name         02.GM_xmlhttpRequest演示
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://bbs.tampermonkey.net.cn/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @require      file://D:\develop\phpstudy_pro\WWW\studyMaster\油猴脚本\day3\02.GM_xmlhttpRequest演示.js
// @grant        GM_xmlhttpRequest
// @connect      bbs.tampermonkey.net.cn
// ==/UserScript==

//index.js
(function () {
    'use strict';
    GM_xmlhttpRequest({
        method: 'GET',
        url: 'https://bbs.tampermonkey.net.cn/home.php?mod=spacecp&ac=favorite&type=thread&id=1268&formhash=fa62a5ea&infloat=yes&handlekey=k_favorite&inajax=1&ajaxtarget=fwin_content_k_favorite',
        onload: (response) => {
            console.log(response,response.response)
        }
    })
})();

@connect

  • 设置允许通过GM_xmlhttpRequest连接访问的域名(包括子域名)。
  • 说白了就是如果在调用@GM_xmlhttpRequest的时候,好像会有一个确认访问域的对话框

代码编写前置工作

前置工作1-@require引入本地文件

  • 方式1:可以在油猴那边编写,然后运行
  • 方法2:借助于@require引入本地文件,然后借助于第三方编辑器进行编写
    • 注意,需要开启允许访问文件网址才可以引入本地文件

  • 然后将下面的文件路径替换为你自己的就好了
    • @require file://文件路径: 将文件路径替换为自己的
// ==UserScript==
// @name         我的脚本开发
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://*/*
// @match        https://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @require      file://文件路径
//比如我的如下
// @require 	 file://D:\develop\phpstudy_pro\WWW\vue\classWork\油猴\1.helloworld.js
// @grant        none
// ==/UserScript==

前置工作2-添加jQuery便携DOM操作

  • 如果不想用原生的或者原生的会用但是没jQuery方便,可以用jQuery来操作DOM,如下
// ==UserScript==
// @name         我的脚本开发
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://*/*
// @match        https://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @require      https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.js
// @require      file://D:\develop\phpstudy_pro\WWW\vue\classWork\油猴\1.helloworld.js
// @grant        none
// ==/UserScript==

  • 这样子我们编写脚本直接就可以使用了
    • 下面是我文件的helloworld.js内容
(function() {
  'use strict';
  console.log($);
  console.log("你好,世界")
})();

代码正式编写

1.练习-1

  • 一个网页添加一个可操作的方块,并有几个功能按钮,效果图如下

  • 测试网站

    • https://dreamlove.top/53b29abd
  • 具体代码

(function () {
  "use strict";
  //创建外层容器
  const wrapperDOM = $(`<div></div>`).css({
    width: 300,
    height: 150,
    backgroundColor: "hotpink",
    position: "absolute",
    top: 60,
    right: 0,
  });

  const button1DOM = $("<button>点击我滚动到底部</button>");
  const button2DOM = $(
    "<button>点击我将'梦洁小站-属于你我的小天地'更改为'这是我的天下了'</button>"
  );
  const button3DOM = $("<button>点击我发表评论</button>");

  button1DOM.click(() => {
    window.scrollTo(0, document.documentElement.scrollHeight);
  });

  button2DOM.click(() => {
    document.getElementById("site-title").textContent = "这是我的天下了";
  });

  button3DOM.click(() => {
    const temp = Date.now();
    localStorage.removeItem("WALINE_COMMENT_BOX_EDITOR");
    localStorage.removeItem("WALINE_USER_META");
    localStorage.setItem("WALINE_COMMENT_BOX_EDITOR", "自动填充评论" + temp);
    localStorage.setItem(
      "WALINE_USER_META",
      JSON.stringify({
        nick: "自动填充昵称" + temp,
        mail: "自动填充邮箱" + temp,
      })
    );
    window.location.reload();
    window.scrollTo(0, document.documentElement.scrollHeight); //先滚动到底部
    document.documentElement.addEventListener("load", () => {
      window.scroll(0, document.documentElement.scrollHeight);
    });
  });

  wrapperDOM.append([button1DOM, button2DOM, button3DOM]);

  //添加到网页当中
  $("html").append(wrapperDOM).css({
    position: "relative",
  });
})();

2.练习-2-CSDN黑夜模式

2.1个人中心页面黑夜模式添加

  • 先观察vip用户和普通用户看看
    • 普通用户: upward_tomato_javascript,vue,javascript复习之旅-CSDN博客
    • vip用户:LaoYuanPython_老猿Python,PyQt+moviepy音视频剪辑实战,OpenCV-Python图形图像处理-CSDN博客
  • 观察这二个人,后面发现一个类不同

  • 然后我们尝试把user-skin-Black添加上去,发现变化了

  • 我们书写下油猴脚本代码
(function() {
    'use strict';
    const skinDivDOM = document.getElementById('userSkin');
    console.log(skinDivDOM.classList.add('user-skin-Black'))
})();
  • 但是发现顶部还没有变化

  • 观察发现是这一个类的问题
    • vip黑色背景为:csdn-toolbar-dark.css
    • 普通用户背景为:csdn-toolbar-default.css

  • 我们油猴试试添加下这个css文件看看,代码就变成了下面这样子
    • @match后期优化
// ==UserScript==
// @name         day2-实现csdn黑色效果
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        *://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @resource darkToolBarCss https://g.csdnimg.cn/common/csdn-toolbar/csdn-toolbar-dark.css
// @require      file://D:\develop\phpstudy_pro\WWW\studyMaster\油猴脚本\day2-实现csdn黑色效果\index.js
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        GM_addElement
// ==/UserScript==

//index.js内容
(function() {
    'use strict';
    const skinDivDOM = document.getElementById('userSkin');
    //个人页面内容区黑色化
    skinDivDOM.classList.add('user-skin-Black')
    //顶部导航栏黑色化
    const darkToolBarCss = GM_getResourceText('darkToolBarCss')
    GM_addStyle(darkToolBarCss)
})();

  • 添加完成后是这样子的

  • 发现差一点效果和vip的

vip效果

  • 查看代码,然后优化后代码如下
// ==UserScript==
// @name         day2-实现csdn黑色效果
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://blog.csdn.net/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @resource darkToolBarCss https://g.csdnimg.cn/common/csdn-toolbar/csdn-toolbar-dark.css
// @require      file://D:\develop\phpstudy_pro\WWW\studyMaster\油猴脚本\day2-实现csdn黑色效果\index.js
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        GM_addElement
// ==/UserScript==

//index.js内容如下
(function() {
    'use strict';
    const skinDivDOM = document.getElementById('userSkin');
    //个人页面内容区黑色化
    skinDivDOM.classList.add('user-skin-Black')
    //顶部导航栏黑色化
    const darkToolBarCss = GM_getResourceText('darkToolBarCss')
    GM_addStyle(darkToolBarCss)
    //顶部导航栏细节优化
    const toolBarDOM = document.querySelector('#csdn-toolbar .toolbar-inside');
    toolBarDOM.style.background = '#242429';
    //顶部导航栏图片替换
    const toolBarImgDark = document.querySelector('#csdn-toolbar > div > div > div.toolbar-container-left > div > a > img');
    toolBarImgDark.src = 'https://img-home.csdnimg.cn/images/20211028053651.png';
})();

2.2文章内容黑夜模式添加

  • 老样子,观察下标题的样式,看看有什么区别
    • 发现vip用户的黑色背景下的标题多了这个样式,而普通用户没有这个skin-clickm…1.min.css样式文件(不信看网络加载的css文件)

  • 那就很简单了,优化下逻辑代码和添加css,结果如下
// ==UserScript==
// @name         day2-实现csdn黑色效果
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://blog.csdn.net/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @resource darkToolBarCss https://g.csdnimg.cn/common/csdn-toolbar/csdn-toolbar-dark.css
// @resource darkArticleCss https://csdnimg.cn/release/blogv2/dist/pc/themesSkin/skin-clickmove/skin-clickmove-3ae5e69ee1.min.css
// @require      file://D:\develop\phpstudy_pro\WWW\studyMaster\油猴脚本\day2-实现csdn黑色效果\index.js
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        GM_addElement
// ==/UserScript==


//index.js
(function() {
    'use strict';
    /**
     * 个人中心黑色背景化
     */
    const skinDivDOM = document.getElementById('userSkin');
    if(skinDivDOM){
        //个人页面内容区黑色化
        skinDivDOM.classList.add('user-skin-Black')
    }
    //顶部导航栏黑色化
    const darkToolBarCss = GM_getResourceText('darkToolBarCss')
    if(!darkToolBarCss){
        console.error('获取顶部导航栏黑色化样式文件失败,请检查css链接是否失效')
        return;
    }
    GM_addStyle(darkToolBarCss)
    //顶部导航栏细节优化
    const toolBarDOM = document.querySelector('#csdn-toolbar .toolbar-inside');
    if(toolBarDOM){
        toolBarDOM.style.background = '#242429';
    }
    //顶部导航栏图片替换
    const toolBarImgDark = document.querySelector('#csdn-toolbar > div > div > div.toolbar-container-left > div > a > img');
    if(toolBarImgDark){
        toolBarImgDark.src = 'https://img-home.csdnimg.cn/images/20211028053651.png';
    }
    /**
     * 文章黑色背景化
     */
    const darkArticleCss = GM_getResourceText('darkArticleCss');
    if(!darkArticleCss){
        console.error('获取文章黑色背景化样式文件失败,请检查css链接是否失效')
        return;
    }
    GM_addStyle(darkArticleCss)
})();

3.脚本自动化之模拟点击和表单填写

  • 示例网站
    • 油猴中文网 - 油猴脚本分享交流 - Powered by Discuz! (tampermonkey.net.cn)
// ==UserScript==
// @name        01.脚本自动化之模拟点击和表单填写
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://bbs.tampermonkey.net.cn/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @require      file://D:\develop\phpstudy_pro\WWW\studyMaster\油猴脚本\day3\01.脚本自动化之模拟点击和表单填写.js
// ==/UserScript==


//index.js
(function() {
    'use strict';
    const timer = setInterval(() => {
        const loginNameDOM = document.querySelector("input[name = 'username']");
        const loginPassDOM = document.querySelector("input[name = 'password']");
        const loginBtnDOM = document.querySelector("button[name = 'loginsubmit']")
        console.log('循环')
        if(loginNameDOM && loginPassDOM){
            loginNameDOM.value = 'testAccount';
            loginPassDOM.value = 'testPassword'
            //点击登录
            loginBtnDOM.click();
            //界面显示,清空循环
            clearInterval(timer);
        }
    },1000)

})();

4.视频倍速播放

  • 借助于video元素身上的playbackRate属性即可
    • HTMLMediaElement.playbackRate - Web API 接口参考 | MDN (mozilla.org)

5.bilibili一键三连

  • 我们长按三连看看

  • 参数重要的几个
csrf: 发现是从cookie获取

aid:发现可以通过window.__INITIAL_STATE__.aid来获取,至于为什么这样子,服务器渲染知识了,百度~

其他几个可能和投银币数量有关的参数在里面,但是不管他了~
  • 至于为什么是3秒,好像需要等页面加载完成后再插入,否则会无限刷新
// ==UserScript==
// @name         03.b站一键三连
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.bilibili.com/video/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @require      https://cdn.bootcdn.net/ajax/libs/js-cookie/3.0.2/js.cookie.min.js
// @require      file://D:\develop\phpstudy_pro\WWW\studyMaster\油猴脚本\day3\03.b站一键三连.js
// @grant        unsafeWindow
// ==/UserScript==

//index.js

(function() {
    'use strict';
    setTimeout(() => {
        const videoBarDOM = document.querySelector('.video-toolbar-left');
        const btnDOM = document.createElement('button');
        btnDOM.textContent = '三连';
        btnDOM.onclick = () => {
            const aid = unsafeWindow.__INITIAL_STATE__.aid;
            const csrf = Cookies.get('bili_jct');
            fetch('https://api.bilibili.com/x/web-interface/archive/like/triple',{
                method:"POST",
                headers:{
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                credentials:'include',
                body:`aid=${aid}&csrf=${csrf}`,
            }).then((res) => {
                return res.json();
            }).then(result => {
                const code = result.code;
                if(code === 0){
                    alert("三连成功!刷新页面可见");
                }else{
                    alert("三连失败/(ㄒoㄒ)/~~");
                }
            })
        }
        videoBarDOM.append(btnDOM)
    },3000)
})();

6.樱花动漫简易去广告

  • 打开樱花动漫,可以看到一堆广告
    • 布莱泽奥特曼日语 09集—在线播放—樱花动漫,视频高清在线观看 (yinghuavideo.com)

  • 原理很简单,display:none就可以隐藏了,视频播放暂停的广告一开始是display:none,暂停的时候被修改为display:block,所以我们把宽度,高度更改为0就可以了
// ==UserScript==
// @name         05.樱花动漫简易去广告
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://www.yinghuavideo.com/v/*
// @match        https://tup.yinghuavideo.com/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @require      file://D:\develop\phpstudy_pro\WWW\studyMaster\油猴脚本\day3\05.樱花动漫简易去广告.js
// @grant        GM_addStyle
// ==/UserScript==


//index.js
(function () {
    'use strict';
    const url = window.location.href;
    if (url.indexOf('yinghuavideo.com') !== -1) {
        GM_addStyle(`
                #HMcoupletDivleft {
                    display:none !important;
                }
                #HMcoupletDivright {
                    display:none !important;
                }
        `);
        //移除右下角
        const ttt = document.querySelector('divz');
        if (ttt) {
            ttt.style.display = 'none';
        }
    }
    if (url.indexOf('tup.yinghuavideo.com') !== -1) {
        let i = 0;
        const timer = setInterval(() => {
            const tempDOM = document.getElementById('adv_wrap_hh');
            //超过一分钟还没加载出来,取消加载
            if(++i >= 60){
                clearInterval(timer);
            }
            //移除暂停视频广告
            if (tempDOM) {
                tempDOM.style.cssText = 'width:0!important;height:0!important';
                clearInterval(timer);
            }
        },1000)
    }

})();

  • 效果

7.bilibili小尾巴-hook思想

  • 我们发送一个消息看看

  • 参数有下面这些

  • 发送的方式是fetch

  • 有关于怎么拦截重写fetch,这个文章说的很好

    • JavaScript 中如何拦截全局 Fetch API 的请求和响应? - 掘金 (juejin.cn)
  • 这里就使用博主的猴子补丁(monkey patching)

const { fetch: originalFetch } = window;

window.fetch = async (...args) => {
    let [resource, config ] = args;
    // request interceptor here
    const response = await originalFetch(resource, config);
    // response interceptor here
    return response;
};
  • 代码如下
    • decodeURIComponent目的是小尾巴所有的字符都编码,不管是不是特殊字符
// ==UserScript==
// @name         06.bilibili小尾巴-hook思想.js
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.bilibili.com/video/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @require      file://D:\develop\phpstudy_pro\WWW\studyMaster\油猴脚本\day3\06.bilibili小尾巴-hook思想.js
// @grant        unsafeWindow
// ==/UserScript==

//index.js
(function() {
    'use strict';
    let tailContent = '\n-----我是可爱的小尾巴'
    const { fetch:originalFetch } = unsafeWindow;
    unsafeWindow.fetch = async (...args) => {
        let [ resource,config ] = args;
        //resource 网站url
        if(resource.includes('api.bilibili.com/x/v2/reply/add')){
            //config 请求设置
            let { body } = config || {};
            const newBody = body.replace(/message=(.*?)&/,(match,$1) => `message=${$1}${decodeURIComponent(tailContent)}&`)
            config.body = newBody;
        }
        const response = await originalFetch(resource,config);
        return response
    }
})();

效果

链接

  • 油猴官方文档
    • https://www.tampermonkey.net/documentation.php
  • post请求提交的数据
    • Content-Type:application/x-www-form-urlencoded

  • 点击查看源

  • 我们的却是这样子

  • 点击查看源

         fetch('https://api.bilibili.com/x/web-interface/archive/like/triple',{
                method:"POST",
                headers:{
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.62'
                },
                credentials:'include',
                body:JSON.stringify({
                    aid,
                    csrf,
                    eab_x: 2,
                    ramval: 13,
                    source: 'web_normal',
                    ga: 1,
                })
            }).then((res) => {
                return res.json();
            }).then(json => {
                console.log('结果',json)
            })
  • 错误原因,我使用了json方式发送数据,这种对应的Content-type应该为application/json

    • 而哔哩哔哩那种是Content-Type为application/x-www-form-urlencoded,也就是类似于key=value&key2=value2…这种形式
    • 而Content-Type为form-data,一般是文件上传的,如下图

    Content-Type为form-data

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1046035.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023/9/26 -- ARM

【计算机相关理论】 1.计算机的组成 输入设备、输出设备、存储器、运算器、控制器 1.输入设备&#xff1a;将编写好的软件代码以及相关的数据输送到计算机中。转换成计算机可以识别、存储 和处理的数据。 例如&#xff1a;鼠标、键盘、复印机、传感器 2.输出设备&a…

结构型设计模式——组合模式

摘要 组合模式(composite pattern): 允许你将对象组合成树形结构来表现"整体/部分"层次结构. 组合能让客户以一致的方式处理个别对象以及对象组合。 一、组合模式的意图 将对象组合成树形结构来表示“整体/部分”层次关系&#xff0c;允许用户以相同的方式处理单独…

【Java SE】Lambda表达式

目录 ♫什么是Lambda表达式 ♫Lambda表达式的语法 ♫函数式接口 ♫Lambda表达式的使用 ♫变量捕获 ♫ Lambda表达式在集合中的使用 ♪Collection的foreach()&#xff1a; ♪List的sort()&#xff1a; ♪Map的foreach() ♫什么是Lambda表达式 Lambda 表达式是 Java SE 8中一个…

Socks5代理IP是什么?有什么优点及如何使用?

随着网络威胁和数据泄露的数量不断增加&#xff0c;在浏览互联网时保护个人信息并保持匿名变得至关重要。实现此目的的一种有效方法是使用Socks5代理IP。如今Socks5代理被广泛应用于跨境电商/社媒平台、SEO业务、网络抓取等领域&#xff0c;在这篇文章中&#xff0c;我们将讨论…

服务好的CMDB运维管理平台的服务优势

随着公司信息化程度的不断提高&#xff0c;IT基础设施也越来越复杂。为了方便这些基础设施的管理和维护&#xff0c;CMDB&#xff08;配置管理数据库&#xff09;运维管理平台应运而生。本文将介绍一个服务好、价格实惠的CMDB运维管理平台&#xff0c;帮助读者更好地了解和使用…

扫地机器人经营商城小程序的作用是什么

扫地机器人对人们生活大有帮助&#xff0c;近些年也有不少企业开创品牌&#xff0c;在电商平台每年销量也非常高&#xff0c;同行竞争激烈及私域化程度加深情况下&#xff0c;虽然第三方平台或线下方式也有生意&#xff0c;但互联网电商发展也为商家们带来了诸多痛点。 那么通…

CRM软件系统如何选择部署方式

CRM的部署方式是选型的主要衡量标准&#xff0c;云部署CRM系统指应用程序在技术商的公有云上&#xff0c;本地化部署将应用程序架设在本地基础设施上&#xff0c;享有应用的所有权。那么CRM系统选择云部署还是本地化部署&#xff1f; 1.云部署CRM系统性价比更高 我们知道本地…

HTTP 跨域名请求(CORS)

同源策略 出于安全考虑&#xff0c;浏览器会限制脚本中发起的跨域请求。比如&#xff0c;使用 XMLHttpRequest 对象和Fetch发起 HTTP 请求就必须遵守同源策略。 具体而言&#xff0c;Web 应用程序通过 XMLHttpRequest 对象或Fetch能且只能向同域名的资源发起 HTTP 请求&#x…

python通过csv库处理CSV文件

CSV库还有其他处理CSV的方法&#xff0c;这里只是介绍几个常用的&#xff0c;后面如果用到别的会进行更新 目录 1 生成一个新的csv文件&#xff0c;并向其中写一点东西 2 单纯往里面写几行 3 读取csv文件 1 生成一个新的csv文件&#xff0c;并向其中写一点东西 import…

工作中Git管理项目和常见问题处理

工作中Git管理项目和常见问题处理 Git仓库的管理方式为什么会出现无法push到线上处理方法 Git仓库的管理方式 共用统一仓库,不同开发人员使用不同分支 步骤 下载代码 git clone <url>查看分支 git branch创建并切换分支 git checkout -b dev分支名称保持和远程分支一…

crypto:Rabbit

题目 根据题目下载压缩包后解压&#xff0c;可得到文本提示 知识盲区&#xff0c;去了解一下Rabbit加密的密文特征 AES、DES、RC4、Rabbit、Triple DES&#xff08;3DES&#xff09; 这些算法都可以引入密钥&#xff0c;密文特征与Base64类似&#xff0c;明显区别是秘文里​​…

使用U3D、pico开发VR(一)——将unity的场景在设备中呈现

最近srtp项目在赶进度&#xff0c;自己之前是在电脑端进行的开发。但是项目是VR端&#xff0c;因此需要重新学习&#xff0c;在此记录一下自己的学习经历。 首先&#xff0c;如何将unity的场景在自己的眼镜中进行呈现呢&#xff1f; 对此&#xff0c;我也找了很多教程&#xff…

关于redis的一主三从三哨兵的实现

关于redis的一主三从三哨兵的实现 前言docker相关的docker-compose.ymlsentinel.conf重点解释一下上面的语句 前言 当谈到数据库管理系统时&#xff0c;Redis就像是那个充满魔法的巫师&#xff0c;能够让你的应用程序变得更快、更可靠&#xff0c;就像是施了魔法一样。而今天&…

HONEYWELL 05704-A-0145

HONEYWELL 05704-A-0145电源模块通常用于为其他设备或系统提供电力供应&#xff0c;以确保它们正常运行。HONEYWELL 05704-A-0145电源模块的应用领域可以非常广泛&#xff0c;包括但不限于以下几个领域&#xff1a; 工业自动化&#xff1a;HONEYWELL 05704-A-0145电源模块用于工…

NEON优化:性能优化经验总结

NEON优化&#xff1a;性能优化经验总结 1. 什么是 NEONArm Adv SIMD 历史 2. 寄存器3. NEON 命名方式4. 优化技巧 Reference: NEON优化&#xff1a;性能优化经验总结NEON官方内联函数Arm NEON programming quick referenceLearn the architecture - Neon programmers’ guide …

Windows server 2022(2023年9月 映像更新 - 20348.1970)安装测试

本文记录了Windows server 2022(2023年9月 映像更新 - 20348.1970)的安装测试过程。 一、检查ISO 简体中文 - Windows Server 2022&#xff08;2023年9月更新 - 20348.1970&#xff09; 内含版本&#xff08;Windows Server 2022 Standard、Windows Server 2022 Standard (D…

期权定价模型系列【6】:欧式期权、百慕大期权、美式期权的定价模型与对比【蒙特卡洛模拟、二叉树模型】

期权定价模型系列第6篇文章 1. 前言 对于欧式期权&#xff0c;最常用的是BS模型&#xff0c;此外&#xff0c;也可也用蒙特卡洛模拟方法求解欧式期权的价格。当然&#xff0c;对于美式期权&#xff0c;也同样可以用蒙特卡洛模拟方法来求解&#xff0c;一般对美式更多用的是二叉…

Kubernetes(K8s):未来云原生应用的引擎

文章目录 Kubernetes的核心概念和架构为什么K8s是构建云原生应用的首选工具&#xff1f;云原生应用的好处和挑战容器编排的重要性&#xff1a;Docker和KubernetesKubernetes生态系统&#xff1a;核心组件和附加工具实际应用&#xff1a;企业如何在生产环境中使用K8s未来展望&am…

基于大语言模型扬长避短架构服务

秘诀&#xff1a; 扬泛化之长&#xff0c; 避时延之短

Linux socket 字节序

socket介绍 字节序 验证什么字节序 #include<stdio.h> int main() {union {short value;char btypes[sizeof(short)];} test;test.value 0x0102;if(test.btypes[0] 1 && test.btypes[1] 2) {printf("大端字节序\n");}else{printf("小端字节序…