油猴(篡改猴)学习记录
第一个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-256
和MD5
哈希 - 如果给出多个哈希(用逗号或分号分隔),则当前支持的最后一个哈希值由 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_getResourceText
和GM_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
对象里面的信息 - 注意
unsafeWindow
和window
是不一样的 - 比如有一个网页,代码如下
<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
- vip黑色背景为:
- 我们油猴试试添加下这个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的
- 查看代码,然后优化后代码如下
// ==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 hereconst response = await originalFetch(resource, config);// response interceptor herereturn 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 网站urlif(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,一般是文件上传的,如下图
相关文章:
油猴(篡改猴)学习记录
第一个Hello World 注意点:默认只匹配了http网站,如果需要https网站,需要自己添加match https://*/*代码如下 这样子访问任意网站就可以输出Hello World // UserScript // name 第一个脚本 // namespace http://tampermonkey.net/ // version 0.1 // descri…...
LeetCode 面试题 05.08. 绘制直线
文章目录 一、题目二、Java 题解 一、题目 已知一个由像素点组成的单色屏幕,每行均有 w 个像素点,所有像素点初始为 0,左上角位置为 (0,0)。 现将每行的像素点按照「每 32 个像素点」为一组存放在一个 int 中,再依次存入长度为 le…...
机器人中的数值优化|【六】线性共轭梯度法,牛顿共轭梯度法
机器人中的数值优化|【六】线性共轭梯度法,牛顿共轭梯度法 往期回顾 机器人中的数值优化|【一】数值优化基础 机器人中的数值优化|【二】最速下降法,可行牛顿法的python实现,以Rosenbrock function为例 机器人中的数值优化|【三】无约束优化…...
FastestDet---原理介绍
1.测试指标 2.算法定位 FastestDet是设计用来接替yolo-fastest系列算法,相比于业界已有的轻量级目标检测算法如yolov5n, yolox-nano, nanoDet, pp-yolo-tiny, FastestDet和这些算法根本不是一个量级,FastestDet无论在速度还是参数量上,都是要小好几个数量级的,但是精度自然…...
ORACLE 在内存管理机制上的演变和进化
截止目前,计算机内存仍然被认为是我们可以获得的最快速度的物理存储设备。 将频繁访问的数据尽可能地置于内存中,已成为当前各种软件和应用程序提高数据访问性能,减少访问延迟的最为有效的途径。 然而,内存作为关键的计算资源&am…...
Linux ❀ 进程出现process information unavailable时的消除方法
[rootmaster ~]# jps 74963 -- process information unavailable 78678 Jps [rootmaster ~]# cd /tmp/hsperfdata_redhat/ # redhat为启动该java进程的用户ps -ef | grep $pid查找 [rootmaster hsperfdata_redhat]# ll total 32 -rw------- 1 redhat redhat 32768 Sep 27 15:…...
ps智能填充功能平替:alpaca的安装和使用
为了解决ps beta 智能填充无法使用的问题,需要用alpaca来平替,下面是安装教程: 安装方法: 1、下载插件。 alpaca插件汉化-夸克网盘https://pan.quark.cn/s/1168b447a44e#/list/share 2、 根据使用的PS版本,选择对应文件…...
【前端打怪升级日志之ES6篇】玩转函数
学习资料 阮一峰老师《ECMAScript 6 入门》— 函数的扩展 总结应用 1. 函数参数默认值与对象解构赋值默认值的结合使用 // 场景:方法调用时传参希望只传第二个参数 // 方案1: function foo({x1,y2}){console.log(x,y); } foo({}) //1 2 foo({x:2}) /…...
网址静态码手机制作教程,附图文详解!
网址的静态码是如何生成的呢?静态码是二维码的一种常用类型,一般常见的静态码类型主要是文本或者网址,那么在电脑制作静态码的方法相信很多小伙伴都知道怎么做,那么手机上制作的方法,大家感兴趣吗?下面来给…...
服务器性能测试监控平台export+prometheus(普罗米修斯)+grafana搭建
1. export 数据采集工具 简介: export是prometheus是的数据采集组件的总称,它可以将采集到的数据转为prometheus支持的格式 node_export: 用来监控服务器硬件资源的采集器,端口号为9100mysql_export: 用来监控mysql数据库资源的采集器&…...
【24种设计模式】责任链模式
责任链模式是一种行为设计模式,它允许你将请求沿着处理链进行传递,直到有一个处理者能够处理该请求为止。这种模式将请求的发送者和接收者解耦,使多个对象都有机会处理该请求。 责任链模式的结构 责任链模式由以下几个角色组成:…...
C#异步委托的三种实现 BeginInvoke / EndInvoke / IsCompleted
本文将介绍C#异步委托的三种实现方式,并给出相关示例代码及解析。 注意事项 用委托开启线程的前提是:创建项目时必须选择“.NET Framework",如果选择的是”.Net Core“,在调用BeginInvoke时,系统会报错”Operati…...
在HTTP请求中安全传输base64编码的字符串
前言 base64是一种常见的的编码格式,它可以把二进制数据编码成一个由大小写英文字母(a-zA-Z)、阿拉伯数字(0-9),以及三个特殊字符、/、组成的字符串。 问题 但是在URL传输中,、/、这三个特殊…...
05预测识别-依托YOLO V8进行训练模型的识别——对视频中的图片进行识别
在前面的一些章节中,我们已经讲如何准备打标签的素材、如何制作标签、如何训练以及得到我们最终需要的用于YOLO目标识别的模型。那么现在我们就要正式开始,利用我们训练得到的best.pt,这个模型文件来对图片视频进行识别。 1、基本思路 公安交管场景中,我们经常会遇到需要…...
LeetCode算法题---第3天
注:大佬解答来自LeetCode官方题解 121.买卖股票的最佳时期 1.题目 2.个人解答 function maxProfit(prices) {//更新最低价格和最大利润let minPrice prices[0];let maxProfit 0;for (let i 1; i < prices.length; i) {// 如果当前价格比最低价格还低,更新最…...
欧洲FBA专线海运与陆运的差别
随着全球电商市场的快速发展,越来越多的卖家选择将产品销售到欧洲市场。然而,面对欧洲境内的物流问题,卖家们往往会面临一个重要的选择:选择欧洲FBA专线时是选择海运还是陆运?这两种运输方式在时效、成本和服务质量上都有所不同&…...
UDS诊断
一、UDS诊断简介 汽车诊断技术是指在不拆卸车辆的情况下,通过读取车辆在运行过程中所记录的数据或故障码来查明故障原因,并确定故障部位的汽车应用技术。通过诊断,可以快速检测到汽车故障来提高汽车安全性和维修效率。 USD协议诊断主要采用“…...
计算材料学学习记录1
计算材料学学习记录1 平台:Bohrium 老师:单斌教授 文章目录 1.发展史背景计算材料学 2.计算方法分类3.计算材料学的应用 1.发展史 背景 材料的研究方法发展: 一切靠实验理论开始起作用理论撑起半边天 “……解决全部化学的规律的数学方法…...
PHP8中的构造方法和析构方法-PHP8知识详解
今日分享的内容是php8中的构造方法和析构方法,我们把构造方法和析构方法这两个方法分开来讲: 1、构造方法 构造方法存在于每个声明的类中,主要作用是执行一些初始化任务。如果类中没有直接声明构造方法,那么类会默认地生成一个没…...
【GPU编程】Visual Studio创建基于GPU编程的项目
vs创建基于GPU编程的项目 🍊前言🐸方法一-CUDA Runtime生成😝debug设置 🍅方法二-空项目配置🍉🍉🍉代码验证 🍊前言 cuda以及cudnn的安装以及系统环境变量的配置默认已经做完。如果…...
MySQL面试题-索引的基本原理及相关面试题
先了解一下MySQL的结构 下面我们重点讲一下存储引擎 MySQL的数据库和存储数据的目录是一一对应的,这些数据库的文件就保存在磁盘中对应的目录里 下面我们来看一下对应的具体数据文件 .frm是表的结构,不管什么样的索引都会有 .ibd代表我们现在使用的存…...
MySQL学习笔记19
MySQL日志文件:MySQL中我们需要了解哪些日志? 常见日志文件: 我们需要掌握错误日志、二进制日志、中继日志、慢查询日志。 错误日志: 作用:存放数据库的启动、停止和运行时的错误信息。 场景:用于数据库的…...
为什么u盘在mac上显示不出来
插入U盘是个看似简单的操作,但有时候在Mac电脑上却出现了无法显示U盘的情况。这样的问题是非常让人头疼的,特别是当你急需使用U盘中的文件时。那么,究竟为什么U盘在Mac上会显示不出来呢?今天就让我们一起来深入了解一下这个问题&a…...
【golang】调度系列之sysmon
调度系列 调度系列之goroutine 调度系列之m 调度系列之p 在golang的调度体系中,除了GMP本身,还有另外一个比较重要的角色sysmon。实际上,除了GMP和sysmon,runtime中还有一个全局的调度器对象。但该对象只是维护一些全局的数据&…...
货物寄到英国选择什么物流比较划算?
随着全球化的发展,越来越多的企业开始将产品销售到海外市场,其中英国作为一个重要的贸易伙伴,吸引了大量的中国企业的关注。然而,如何将货物安全、快速地运送到英国,成为了众多企业面临的一个问题。那么,货…...
vite + react 基本项目搭建
新建项目步骤略过 1、下载scss 无需任何配置就可以直接使用scss了 pnpm install sass使用scss配置全局颜色变量 新建/src/styles/variable.scss并在 $primary: #76aef9在vite.cinfig.js里配置 export default defineConfig({css: {preprocessorOptions: {scss: {javascrip…...
一个方法解决三道区间问题
1288. 删除被覆盖区间 56. 合并区间 986. 区间列表的交集 # 1288. 删除被覆盖区间 class Solution:def removeCoveredIntervals(self, intervals: List[List[int]]) -> int:# 按照起点升序排列,起点相同时,按照终点降序排列intervals.sort(key lamb…...
sub0 里斯本精彩回顾:探索波卡区块的创新空间
sub0 Europe 2023 已在葡萄牙里斯本圆满结束!sub0 大会是波卡生态开发者大会,由波卡协议的主要开发方 Parity Technologies 举办的开发者大会,汇聚了全球 Substrate 开发者和学习者,旨在为 Polkadot 和 Kusama 生态的开发者、贡献…...
颜色+情感的英语表达还有这些,零基础学英语口语去哪里,柯桥有推荐的吗?
当我们探讨关于"blue"(蓝色)的多义性时,我们会发现英语中有许多其他词汇也有类似的双关意义。 既可以表示一种颜色或物理属性,又可以代表一种情感或心理状态。 这种现象在语言中很常见,反映了语言的丰富性和…...
exoplayer的使用-6,播放器的选择
需要一个能播放蓝光的,高码率的播放器,在使用现成的播放器的基础上,可选的有几个,exoplayer,vlc,ijk,mpv. exoplayer的更新频繁,适应性强,扩展性一般,因为它基于系统的硬解,音频可扩展,使用ffmpeg可以解决. 有国际化支持,音频,字幕这些显示效果好. 对杜比视频,hdr这些支持看设…...
网站开发+职位描述/seo入门到精通
命令提示符打开资源管理器Searching for a file in Windows Explorer takes forever, but there’s a faster way if you’re willing to use the command prompt. 在Windows资源管理器中搜索文件需要花费很多时间,但是如果您愿意使用命令提示符,则可以采…...
网页游戏宣传片排行榜/自动app优化下载
VSFTP全称为Very Safe Ftp,可见相对于Linux的其它FTP版本安全性有了很大的提高。<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />本人曾为某一学院创建了一个FTP站点,其中学生只能只读,而教师可以写入。以…...
dede网站怎么做单页面/软件网站排行榜
点击上方“蓝色字”可关注我们!暴走时评:IT业巨头富士通日前推出一项新的咨询服务,并表示该服务将在短短五天内实现“随时可用”的区块链最低可行产品研发。该服务起价9900欧元,内容包括从区块链技术基础入门课程、拟议用例评估再…...
网站建设挣钱吗/潍坊网站建设优化
0 序言泰勒公式,本质上是一种函数的近似,强大之处就在于可以将不同类型的函数,统一用多项式求和的形式进行替换,从而变成多项式的运算。本篇主要是标出常见的几个泰勒展开式、高阶无穷小的计算规则、泰勒公式使用时应该展开到第几…...
建筑bim工程网报入口/如何优化关键词排名快速首页
1.题目描述 题目来源:https://pintia.cn/problem-sets/14/problems/734 基础编程题目集 760 分 函数题共 13 小题,共计 185 分编程题共 38 小题,共计 575 分 函数题编程题 6-2 多项式求值 (15 分) 函数接口定义&…...
网络营销方式有哪些自动售货机景区运营/网站seo搜索引擎优化教程
介绍 官方文档 常用模板语法 只需要记两种特殊符号: {{ }} 和 {% %} 变量相关的用{{}} 逻辑相关的用{%%} 变量 {{ 变量名 }} 变量名由字母数字和下划线组成。 点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值。 几个例…...