前言
本文全程使用原生JavaScript进行编程,不使用像jQuery这样的第三方库
视频链接
零基础油猴脚本编写指南【上】 (对应0x01~0x05)
0x00 前置知识
本节简单的介绍一下一些名词的概念,了解为主,直接跳过也是可以的
-
HTML、CSS和JS
HTML即超文本标记语言,它用来描述各种网页元素,类似与一份清单,浏览器读取以后根据它来加载对应的资源
CSS即层叠样式表,它只用来描述网页元素的外观,还可以添加少许动画,但是不影响功能
JS即JavaScript,它是一种网页脚本语言,用来让静态的网页能够响应各种动作,
还可以挖矿如果把HTML比作木偶,那么CSS就是木偶的衣服,JS就是木偶的提线,用来操控木偶
-
油猴和浏览器
当你访问链接的时候,浏览器会先下载链接对应的文件(通常是一个HTML文件),然后根据HTML描述的对象列表,来下载图片、视频等资源,有的CSS和JS内嵌在HTML文件里,有的则是单独的文件,等必要的资源加载完成以后,浏览器才能生成可以交互的网页
油猴实际上是一个加载器,它把用户脚本安插在最开始获取到的HTML文件中,这样浏览器加载网页的时候,也会加载特定的用户脚本,这样我们就能够通过编写用户脚本来修改网页了
-
HTML5和DOM
HTML5是现行的HTML标准,DOM即文档对象模型,是一用对象表示HTML标签的方法,通过DOM,我们可以简单的修改文档对象的属性,来轻松修改HTML标签的内容
0x01 初识开发者工具
工欲善其事必先利其器,本节简单的介绍一下开发者工具的使用。
本节以我的博客作为演示,地址:chrxw.com
个人比较喜欢Firefox的开发者工具,以下介绍均使用Firefox进行演示,如果使用Chrome的话可能布局会有细微差异,不过功能是类似的。
Chrome自带的开发者工具貌似没有汉化,建议使用别的Chromium内核的浏览器(比如新版Edge),功能都差不多。
-
在浏览器中按
F12
即可打开开发者工具 -
查看器,左侧可以查看页面的HTML内容,右侧显示的是选中的DOM元素的CSS
-
控制台,可以运行自己编写的JS代码。
也可以在设置里打开“分离式控制台”,这样就可以在所有TAB里都显示控制台了。
-
调试器,可以用来单步调试JS
-
网络,可以查看浏览器的网络请求
-
储存,在这个TAB中可以查看网站在本地保存的内容,最常用的是Cookie,其次是LocalStorge(本地储存),还有个由浏览器自动管理的Session(会话储存),JS可以访问的只有Cookie和LocalStorge。
0x02 初识DOM
本节通过使用开发者工具,简单的演示一下如何操作DOM元素,以我的博客作为演示,地址:chrxw.com
-
首先打开开发者工具,然后激活选择器,然后点击“标题”,这样在右边的查看器中就会显示我们点击的对象
-
右键高亮的元素,然后点击“在控制台使用”(如果是Chromium或者Chrome,点击“复制”/“Copy”->“复制JS路径”/“Copy JS path”,然后把复制结果粘贴到控制台中)
-
Firefox自动创建了一个
temp0
变量,按一下回车,可以看到控制台输出了一个DOM元素,点一下左边的箭头展开,可以看到这个对象的各种属性。 -
接下来我们尝试修改一下它的内容
按回车执行,然后可以看到,网页的标题已经被修改了
-
接着我们修改一下CSS,让它居中显示
-
接下来我们创建一个新的DOM元素,然后插入到网页中
点一下新出现的按钮,可以看到消息弹窗
代码讲解:
PS: document 也是DOM元素,它代表整个网页,其他DOM元素都是它的子集。
-
这两行代码创建了一个
button
对象,它内部的文本为按钮
,由浏览器自动生成的HTML表达式为<button>按钮</button>
-
这三行代码为
btn
对象添加了事件监听器,addEventListener
的第一个参数是事件监听器的名称,第二个参数是接收到指定事件后调用的函数,()=>{ ... }
是匿名函数的缩略写法,匿名函数还有另一种等效写法function(){ ... }
,或者写成普通函数,也是可以的。添加好事件监听器以后,点一下按钮,就会触发
click
事件,然后由浏览器调用我们绑定的方法alert('hello world');
,弹出消息框 -
A.appendChild(B)
的作用是把B元素插入到A元素的子元素的末尾,也就是把btn
对象插到temp0
中,由浏览器自动帮我们修改了HTML文本
-
-
通过操作DOM元素的属性,就可以很方便的修改网页的显示效果,添加各种功能。
0x03 DOM进阶之获取DOM元素
通过修改DOM元素的属性,可以很方便地修改网页,但是首先我们得获取我们想要修改的DOM元素
本节将会介绍如何获通过代码获取现存的DOM元素,以我的博客作为演示,地址:about.html
1. 使用ID进行获取
WEB开发者设计网页的时候,会给一些经常需要修改的元素添加
id
属性,原则上每个元素的id
都是不同的,所以如果某个元素具有id
属性,我们就可以使用getElementById
来获取需要注意的是,如果元素没有
id
属性的话这个方法就行不通了
随便打开一篇博文,最下面的评论框是带有id
属性的,使用开发者工具我们可以看到,它的id
为comment
我们可以用document.getElementById( id名称 )
的方式获取DOM元素
代码非常好理解,先调用getElementById
方法获取DOM,然后修改它的value
属性,效果就是文本框的内容被修改了
PS: textContent 属性修改的是HTML文本,而 value 属性修改的是文本框中的内容,不影响HTML文本
2. 使用CSS选择器进行获取
在一个网页中,具有
id
属性的元素不会太多,大多数时候都是没有这个属性的,这时候可以根据元素的class
属性,使用querySelector(获取符合条件的第一个元素)
或者querySelectorAll(获取符合条件的全部元素数组)
进行获取本节只介绍常用的方法,更详细的介绍可以参考这个:CSS 选择器参考手册
-
根据
class
进行选择标题元素的
class
为entry-title m-n font-thin text-black l-h
,class
选择器的语法为.
+class名称
,如果有多个class
名称,则用.
分隔所以标题元素的选择器写法为
.entry-title.m-n.font-thin.text-black.l-h
在CSS选择器语法中,空格代表子元素的意思,所以不能随意添加空格。
通过搜索,我们发现
entry-title
在HTML文档只出现了一次,因此选择器也可以简化写作.entry-title
,代码如下在实际运用中,没必要给出完整的
class
,只需要写独一无二的部分即可 -
根据
id
进行选择(可以用,但还是建议用getElementById
)id
选择器的语法为#
+id名称
,评论框的id
是comment
,所以选择器写法为#comment
,代码如下 -
根据元素类型选择
还可以根据DOM元素的类型进行选择,如果网页中只有一个特定种类的元素,那么直接写元素类型即可
使用开发者工具,我们可以知道,评论框的类型为
textarea
,而且整个网页只有一个textarea
,因此选择器可以直接写成textarea
,代码如下 -
根据相对关系进行选择
有的时候,想要操作的元素可能没有独一无二的属性,那么就可以根据相对关系进行选择
A>B
表示在A
的一级子元素中查找B
A B
表示在A
的内部查找B
(查找范围不仅包括子元素,还包括孙元素等)A+B
表示与A
相邻的B
元素(平级关系,非父子关系)这里的 A 和 B 代表的是选择器,选择器可以嵌套使用。
A.B
,不表示相对关系,它表示类型是A
,class
名是B
的元素,这个要注意。还是用标题元素举例子
先找到容易定位的元素,然后再根据相对关系寻找想要找的元素,方法有很多,下面举几个例子
写成这个样子主要是为了举例子,实际使用中选择器越简洁越好
-
根据其他属性名称进行选择
[xxx]
选择带有xxx
属性的元素[xxx=sss]
选择xxx
属性等于sss
的元素[xxx~=sss]
选择xxx
属性包含sss
的元素(sss
必须是整个单词)[xxx|=sss]
选择xxx
属性以sss
开头的元素(sss
必须是整个单词)[xxx^=sss]
选择xxx
属性以sss
开头的元素(sss
可以是单词的一部分)[xxx$=sss]
选择xxx
属性以sss
结尾的元素(sss
可以是单词的一部分)[xxx*=sss]
选择xxx
属性包含sss
的元素(sss
可以是单词的一部分)通过开发者工具可以看出高亮的DOM元素具有
for
属性,属性值为comment
,代码如下,感受一下几种用法的区别 -
组合选择器
上面介绍过的选择器可以组合使用,比如选择表情按钮中的矢量图片
代码如下,自己体会一下各个部分是什么意思,以及哪些部分是没有必要的
0x04 DOM进阶之修改DOM元素
拿到了DOM对象,接下来就可以进行各种操♂作了
本节将会介绍DOM元素的常用方法,以我的博客作为演示,地址:about.html
以标题元素为例,首先我们先获取DOM对象
使用开发者工具可以非常方便的看到DOM元素的方法和属性
枚举子元素
DOM.children
返回值为DOM元素的所有子元素数组,如果不含有子元素,返回的是空数组。
可以通过DOM.children[i]
的方式获取某一个子元素
获取/修改文本内容
DOM.textContent
返回值为当前DOM元素内的显示字符(没有被 < > 包起来的所有字符),不仅包括自身,还包括所有子元素
DOM.innerText
也有类似的效果,区别是它会去掉多余的换行符
也可以修改DOM.textContent
和`DOM.innerText
不过要注意的是,这两个方法会直接替换掉元素内部的内容,如果元素内部有其他子元素的话,子元素会消失。
获取/修改元素CSS
只能修改DOM元素的内联CSS,全局CSS得修改Style元素才行。
CSS相关内容不做过多介绍,贴个简单的教程:菜鸟CSS教程
DOM.style
,获取DOM元素的内联CSS样式
DOM.style.[css名称]
,获取DOM元素的特定CSS属性,例如textAlign
DOM.style.cssText
,获取DOM元素的内联CSS样式,纯文本格式
同样的,也可以用类似的方法修改CSS样式
DOM.style.[css名称] = 'xxx'
,修改DOM元素的特定CSS属性为xxx
DOM.style.cssText = 'aaa: xxx;'
,直接修改DOM元素的内联CSS文本,可以一次设置多个CSS
如果想隐藏某些元素的话,可以把它的CSS的
display
属性设置成none
,就会被隐藏起来了
新增子元素
DOM.appendChild( [要插入的DOM对象] )
appendChild
会将新插入的对象放在所有子元素的末尾
DOM.insertBefore( [要插入的DOM对象] , [DOM对象,将要插在这个对象之前])
insertBefore
可以指定新插入的对象的位置
删除对象
DOM.remove()
这是个方法,所以要加()
,调用后会在HTML文本中删除对象对应的内容
添加/删除事件监听器
DOM.addEventListener( [事件名称] , [回调函数])
添加事件监听器
DOM.removeEventListener( [事件名称] , [回调函数])
移除事件监听器
也可以用以前的写法(不推荐):
DOM.on[事件名称] = [回调函数]
添加事件监听器
DOM.on[事件名称] = null
移除事件监听器
比如要让h1
对象响应click
事件,代码如下
删除绑定的方法也是类似的,不再赘述
模拟鼠标点击
DOM.click()
相当于鼠标点了一下DOM对象,触发它的click
事件(如果有的话)
0x05 第一个油猴脚本
讲了这么久,都是在介绍前端的基础知识,接下来开始正文
首先让我们新建一个用户脚本
按Ctrl
+S
即可保存
元信息
元信息是给油猴插件使用的,用来记录脚本的属性
新建脚本时给出的默认元信息如下:
还有部分比较常见的元信息:
代码区域
首先定义了一个匿名函数function() { ... }
,也可以写成我常用的格式,都是等效的:
用()
把匿名函数包起来,再在后面加一个()
,表示直接执行这个匿名函数
其实完全可以把代码写到匿名函数的外部,都可以执行,只是定义域不同而已
'use strict';
是伪代码,它告诉解释器,开启严格模式
开启严格模式以后,会进行更严格的语法检查,建议开启,有利于养成良好的编码习惯
实现功能
接下来我们为脚本编写一些功能,以我的博客作为演示,地址:about.html
-
首先我们需要修改元信息,让脚步只在特定的网页生效
然后添加作者名称和脚本名称(除了@match都可以随便写)
-
我们先不编写脚本,我们先使用开发者工具测试一下代码
首先我们找一个对象下手(如图)
它没有
id
属性,但是它的class
名称独一无二,所以我们可以直接用document.querySelector('.item-thumb')
获取到DOM元素 -
修改元素的背景图
-
添加点击事件
点一下以后背景变成了品红色
-
最后我们编写油猴脚本,让这一切自动完成
保存脚本以后,刷新页面,可以看到元素的背景图片已经改掉了,说明脚本运行成功了。
0x06 脚本实战,Auto_Sub3
脚本获取链接:Auto_Sub3
脚本功能
安装脚本以后,首页可以打开一个面板,主要功能是一键-3
元信息
元信息提供了这个脚本的基本信息,我们还可以知道,它申请了GM_setValue
,GM_getValue
和GM_xmlhttpRequest
三个特殊权限
代码总览
先不用太纠结代码,建议先用调试模式看一下代码流程
脚本调试模式
在设置里可以打开调试模式,开启以后在加载完脚本以后会自动暂停,可以用来动态调试脚本
打开调试模式以后,先打开开发者工具,然后刷新页面,可以看到暂停在debugger
语句上了
给我们感兴趣的函数添加断点,然后点“继续运行(F8)”
可以自己尝试跟踪一下每个函数的运行过程,不再赘述
代码详解
脚本入口
首先定义了5个全局变量,然后运行了匿名函数,在这个匿名函数里完成了脚本的初始化工作
在匿名函数内部调用了这么几个函数:loadCFG
,addBtns
,switchPanel
,autoRoll
loadCFG/saveCFG - 读写配置
脚本保存数据的方法有很多种,可以利用原生的Cookie
,也可以利用HTML5标准中的LocalStorge
,但是这两个地方只能保存文本,我们还需要自行完成类型转换,非常不方便,所以我用的是油猴自带的储存空间
GM_setValue( 键名 , 键值)
,保存某个值
GM_getValue( 键名 )
,如果键名不存在,返回null
可以在脚本编辑器的储存
TAB看到当前脚本的储存空间
saveCFG
非常简单,就是把4个全局变量保存起来
loadCFG
也很简单,就是从储存空间读取4个变量,然后获取现在的时间和日期,判断日期有没有变更,如果日期变了,并且当前小时数大于8
,就把Vcan3
赋值成true
,然后把VLast
改成今天的日期,最后调用saveCFG
保存4个全局变量
addBtns - 添加GUI
看着很长,实际上很简单,首先定义了3和内部函数genButton
,genDiv
,genPanel
,用来生成我们需要的DOM元素
然后尝试用选择器获取DOM对象
可以利用开发者工具看一下是哪个对象
剩下的部分也很好理解,创建3个button
对象,1个img
对象,依次添加到名为panel54
的div
对象里,最后再把panel54
添加到panelArea
中
通过switchPanel
,可以切换显示原来的元素和脚本的面板
运行效果:
autoRoll - 自动-3
最后我们看一下核心功能,自动-3
乍一看非常复杂,实际上也很好理解
-
首先调用
sound.play()
,播放蒸汽泄漏的音效,sound
是全局变量,会在网页载入的时候自动加载音频资源,如果遇到错误就忽略错误(比如网络问题加载音频失败的话就会报错)然后调用了
gethash
方法 -
-
这个函数使用了
GM_xmlhttpRequest
,这个东西是一个网络请求器,深入了解可以参考官方文档(英语),GM_xmlhttpRequest
类似于xmlHttpRequest
,两者用法几乎一样,只是GM_xmlhttpRequest
不存在跨域的问题简单的用法如下
-
看到
onload
的回调函数部分首先判断状态码是不是200(代表请求成功),请求成功才会处理响应的内容
可以在浏览器中打开链接,用开发者工具模拟一下处理过程
我们把响应的内容当做纯文本处理,使用正则表达式提取想要的内容
正则表达式深入学习可以参考这个:正则表达式 - 语法
简单的讲一下上面的正则表达式是什么意思
简单点说就是先找到
plugin.php?id=steamcn_lottery:view&lottery_id=43&hash=[XXXXXXX]&roll
这一串字符串,然后提取中间的XXXXXXX
执行效果如下,可以看到返回了一个数组,第一个元素是匹配到的字符串,第二个元素是子匹配项,我们只需要子匹配项,也就是
8b51a2d3
(这个值不同用户是不一样的,所以需要动态获取)然后就是赋值操作,用到了三目运算符号
如果正则表达式没有匹配到合适的字符串,返回的内容是
null
,逻辑意义等于false
,这时候hash
的值就取null
如果正则表达式匹配到了合适的字符串,返回的内容是数组,逻辑意义等于
true
,这时候hash
的值就取数组的第2个元素然后根据
hash
决定是不是要继续运行
-
-
最后是
roll
函数,核心也是一个网络请求器实际上就是访问
https://keylol.com/plugin.php?id=steamcn_lottery:view&lottery_id=43&hash=[XXXXXXX]&roll
这个网站,然后把响应结果打印出来可以根据上一步得到的
hash
在浏览器中试一下调用以后,会自增
v
,如果v = 3
,就调用disableS3
和saveCFG
,修改了按钮的名称,然后保存全局变量
本文链接:https://blog.chrxw.com/archives/2021/02/08/1449.html
转载请保留本文链接,谢谢
17 条评论
很优秀的大佬
图床崩了。打赏不了哈...
|´・ω・)ノ
|´・ω・)ノ
非常感谢!入门小白拜读。
搜索答案半天,发现无法在匿名函数上调用removeEventListener
目前只有将移除事件写在添加事件当中,满足触发条件之后移除事件;
在F12调试中无法实现添加完之后再进行移除。
前辈辛苦了!拜读中
"GM_setValue( 键名 ),如果键名不存在,返回null",这句写错了:"GM_getValue( 键名 ),如果键名不存在,返回null"
修正了,感谢反馈
你好!我下载了你文中实战的脚本(Auto_Sub3),在脚本编辑器里没有看到"储存"TAB,请问要怎样设置才能看到!我的Tampermonkey版本为 V4.11
脚本要调用过 GM_setValue 才会有“存储”TAB,你可以访问一次 keylol.com,应该就会有“存储”TAB了。
谢谢!
收藏了
添加/删除事件监听器 中 “DOM.addEventLiremoveEventListenerstener( [事件名称] , [回调函数])移除事件监听器” 写错了 ,应该是removeEventListener
感谢指出,已经修正了
好耶 讲的很详细 入门足矣
可以可以,收藏了