本篇目标
- 了解为什么我们需要直接调用 JavaScript
- 了解常见的 Python 调用 JavaScript 的库
- 了解一种性能更高的操作方式
- 知道什么场景下应该使用什么方式进行调用
通过本文的学习,在你写爬虫时,你应该会对调用 JavaScript 有一个更清晰的了解,并且你还要了解到一些你平时可能见不到的骚操作。
大家如果接触过 JavaScript 逆向的话,应该都知道,通常来说碰到 JS 逆向网站时会有这两种情况:
- 简单 JS 破解:通过 Python 代码轻松实现
- 复杂的 JS 破解:代码不容易重写,使用程序直接调用 JS 运行获取结果。
对于简单的 JS 来说,我们可以通过 Python 代码,直接重写,轻轻松松的就能搞定。 而对于复的 JS 代码而言呢,由于代码过于复杂,重写太费时费力,且碰到对方更新这就比较麻烦了。所以,我们一般直接使用程序去调用 JS,在 Python 层面就只是获取一个运行结果,这样做相比于重写而言就方便多了。 那么,接下来我带大家看一下两种比较简单的 JS 代码重写。 本文涉及的所有演示代码请到公众号:AI悦创,后台回复:PJS 。来获取即可!
1. Base64
首先,我们先来看一下 Base64 ,Base64 是我们再写爬虫过程中经常看到的一种编码方式。这边我们来写两个例子。
1 |
// 原字符 |
第一个例子如上,是 NightTeam 经过编码是如上面的结果(TmlnaHRUZWFt),如果我们只是通过这个结果来分析的话,它的特征不是很明显。如果是见的不多或者是新手小白的同学,并不会把它往 Base64 方向去想。 然后,我们来看一下第二个例子:
1 |
// 原字符 |
第二个例子是 aiyuechuang 编码之后的结果,它的末尾有一个等号,Python3 编码之后末尾有两个等号,这个特征相对第一个就比较明显了。一般我们看到尾号有两个等号时应该大概可以猜到这个就是 Base64 了。 然后,直接解码看一看,如果没有什么特别的话,就可以使用 Python 进行重写了。 同学可以使用以下链接 Base64 编码解码的测试学习:http://tool.alixixi.com/base64/ 不过 Base64 也会有一些骚操作,碰到那种情况的时候,我们如果用 Python 重写可能有点麻烦。具体的内容我会在后面的的课程中,单独的跟大家详细的讲解。
2. MD5
第二个的话就是 MD5 ,MD5 在 Javascript 中并没有标准的库,一般我们都是使用开源库去操作。
注意:md5 的话是 哈希 并不是加密。
下面我来看一个 js 实现 md5 的一个例子: md5.js 上面的代码时被混淆过的,但是它的主要一个特征还是比较明显的,有一个入口函数:console.log(hex_md5("aiyuechuang")) 我们可以使用命令行运行一下结果,命令如下:
1 |
node md5.js |
上面的代码自行复制保存为 md5.js 然后运行。
运行结果:
1 |
$ node md5.js |
我们数一下输出的结果的话,会发现这正好 是 32位,通常我们看到 32 位的一个英文数字混合的字符串,应该马上就能想到时 md5 了,这两个操作的话,因为在 Python 中都有对应的库,分别是:Base64 和 hashlib ,大家应该都知道这个我就不多说了。 例程:Base64 和 hashlib
1 |
import base64 |
输出
1 |
b'YWl5dWVjaHVhbmc=' |
1 |
import hashlib |
输出
1 |
e55babec7f5d5cf7bac7872f0481bec1 |
像我们前面看到的那些代码,都是比较简单的,他们的算法部分也没有经过修改,所以我们可以使用其他语言和对应的库进行重写。 但是如果对方把算法部分做了一些改变呢? 如果代码量比较大也被混淆到看不出特征了,连操作后产生的字符串都看不出,我们就无法直接使用一个现成的库来复写操作了。 而且这种情况下的代码量太大了,直接对着代码重写成 Python 版本也不太现实,对方一更新你就得再重新看一遍,这样显然时非常麻烦的,也非常耗时。 那么有没有一种更高效的方法呢? 显然是有的,接下来我们来讲如何通过程序来直接调用 JavaScript 代码,也就是碰到复杂的 JS 时候的处理。
- 使用 Python 调用 JS
- 一种性能更高的调用方式
- 到底选择哪种方案比较好
首先,我会分享一些使用 Python 调用 JavaScript 的方式,然后会介绍一种性能更高的调用。以及具体使用哪种调用方式以及怎么选择性的使用,最后我会总结一下这些方案存在的小问题。并且会告诉你如何踩坑。
3. 使用 Python 调用 JS
我们接下来首先讲一下 Python 中调用 JavaScript。
- PyV8
- Js2Py
- PyExecJS
- PyminiRacer
- Selenium
- Pyppeteer
Python 调用 JS 库的话,光是我了解的话,目前就有这么一堆,接下来我们就来依次来介绍这些库。
3.1 PyV8
- V8 是谷歌开源的 JavaScript 引擎,被使用在了 Chrome 中
- PyV8 是 V8 引擎的一个 Python 层的包装,可以用来调用 V8 引擎执行 JS 代码
- 网上有很多使用它来执行 JS 代码的文章
- 年久失修,最新版本是 2010年的(https://pypi.org/project/PyV8/#history)
- 存在内存泄漏问题,所以不建议使用
首先来看一下什么是 PyV8,V8 是谷歌开源的 JavaScript 引擎,被使用在了 Chrome 浏览器中,后来因为有人想在 Python 上调用它(V8),于是就有了 PyV8。 那 PyV8 实际上是 V8 引擎的一个 Python 层的包装,可以用来调用 V8 引擎执行 JS 代码,但是这个我不推荐使用它,那我既然不推荐大家使用,我为什么又要讲它呢? 其实,是这样的: 虽然目前网上有很多文章使用它执行 JS 代码,但是这个 PyV8 实际上已经年久失修了,而且它最新的一个正式版本还是 2010年的,可见是有多久远了,链接在上方可以执行访问查看。而且,如果你实际使用过的话,你应该会发现它存在一些内存泄漏的问题。 所以,这边我拿出来说一下,避免有人踩坑。接下来我们来说一下第二个 JS2Py。
3.2 Js2Py
- Js2Py 是一个纯 Python 实现的 JavaScript 解释器和翻译器
- 虽然 2019年依然有更新,但那也是 6月份的事情了,而且它的 issues 里面有很多的 bug 没有修复(https://github.com/PiotrDabkowski/Js2Py/issues)。
Js2Py 是一个纯 Python 实现的 JavaScript 解释器和翻译器,它和 PyV8 一样,也是有挺多文章提到这个库,然后来调用 JS 代码。 但是,Js2Py 虽然在2019年仍然更新,但那也是 6月份的事情了,而且它的 issues 里面有很多的 bug 没有修复(https://github.com/PiotrDabkowski/Js2Py/issues)。另外,Js2Py 本身也存在一些问题,就解释器部分来说: 解释器部分:
- 性能不高
- 存在一些 BUG
那不仅仅就解释器部分,还有翻译器部分:
- 对于高度混淆的大型 JS 会转换失败
- 而且转换出来的代码可读性差、性能不高
总之来讲,它在各个方面来说都不太适合我们的工作场景,所以也是不建议大家使用的。
3.3 PyMinRacer
- 同样是 V8 引擎的包装,和 PyV8 的效果一样
- 一个继任 PyExecJS 和 PyramidV8 的库
- 一个比较新的库
这个库也是一个 PyV8 引擎包装,它的效果和 PyV8 的效果一样的。 而且作者号称这是一个继任 PyExecJS 和 PyramidV8 的库,乍眼一看挺唬人的,不过由于它是一个比较新的库,我这边就没有过多的尝试了,也没有再实际生产环境中使用过,所以不太清楚会有什么坑,感兴趣的朋友,大家可以自己去尝试一下。
3.4 PyExecJS
- 一个最开始诞生于 Ruby 中的库,后来被移植到了 Python 上
- 较新的文章一般都会说用它来执行 JS 代码
- 有多个引擎可选,但一般我们会选择使用 NodeJS 作为引擎来执行代码
接下来我要说的是 PyExecJS ,这个库一个最开始诞生于 Ruby 中的库,后来人被移植到了 Python 上,目前看到一些比较新的文章都是用它来执行 JS 代码的,然后它是有多个引擎可以选择的,我们一般选择 NodeJS 作为它的一个引擎执行代码,毕竟 NodeJS 的速度是比较快的而且配置起来比较简单,那我带大家来看一下 PyExecjs 的使用。
3.4.5 PyExecJS 的使用
- 安装 JS 运行环境这里推荐安装 Node.js,安装方便,执行效率也高。
首先我们就是要安装引擎了,这个引擎指的就是 JS 的一个运行环境,这边推荐使用 Node.js。
注意:虽然 Windows 上有个系统自带的 JScript,可以用来作为 PyExecjs 的引擎,但是这个 JScript 很容易与其他的引擎有一个不一样的地方,容易踩到一些奇奇怪怪的坑。所以请大家务必要安装一个其他的引擎。比如说我们这里安装 Node.js 。
那上面装完 Nodejs 之后呢,我们就需要执行安装 PyExecjs 了:
-
安装 PyExecJS
1
pip install pyexecjs
这边我们使用上面的 pip 就可以进行安装了。 那么我们现在环境就准备好了,可以开始运行了。
- 代码示例(检测运行环境)
首先,我们打开 IPython 终端,执行一下一下两行代码,以下也给出了运行结果:
1 |
In [1]: import execjs |
execjs.get() # 查看调用的环境用此来看看我们的库能不能检测到 nodejs,如果不能的话那就需要手动设置一下,不过一般像我上面一样正常输出 node.js 就可以了。 如果,你检测出来的引擎不是 node.js 的话,那你就需要手动设置一下了,这里有两种设置形式,我在下方给你写出来了: 选择不同引擎进行解析
1 |
# 长期使用 |
由上边可知,我们有两种形式:一种是长期使用的,通过环境变量的形式,通过把环境变量改成大写的 EXECJS_RUNTIME 然后将其值赋值为 Node。 另一种的话,将它改成临时使用的一种方式,这种是直接使用 get,这种做法的话,你在使用的时候就需要使用 node 变量了,不能直接导入 PyExecjs 来直接开始使用,相对麻烦一些。 接下来,就让我们正式使用 PyExecJS 这个包吧。
1 |
In [8]: import execjs |
PyExecjs 最简单的用法就是导入包,然后通过 eval 这个方法并传入简单的 JS 代码来执行。但是我们正常情况下肯定不会这么使用,因为我们的 JS 代码是比较复杂的而且 JS 代码内容也是比较多的。
1 |
# -*- coding: utf-8 -*- |
这样的话,我们一般通过使用第二种方式,第二种方式是通过使用 compile 对 JS 字符串进行编译,这个编译操作其实就是把参数(jstext)里面的那段 JS 代码给放到一个叫 Context 的上下文中,它并不是我们平时编译程序所说的编译。然后我们 调用 call 方法进行执行。 第一个参数是我们调用 JS 中的的函数名,也就是 hello。然后后面跟着的 hello aiyc 就是参数,也就是我们 JS 中需要传入到 str 的参数。如果 JS 中存在多个参数,我们就直接在后面打个逗号,然后接着写下一个参数就好了。 接下来我们来看一个具体的代码: aes_demo.js 这边我准备了一个 CryptoJS 的一个 JS 文件,CryptoJS 它是一个包含各种加密哈希编码算法的一个开源库,很多网站都会用它提供的函数来生成参数,那么这边我是写了如上面这样的代码,用来调用它里面的 AES 加密参数,来加密一下我提供的字符串。
注意:JS 代码不要放在和 Python 代码同一个文件中,尽量放在单独的 js 文件中,因为我们的 JS 文件内容比较多。然后通过读取文件的方式,
1 |
# Python 文件:run_aes.py |
这里我通过读取文件的方式,将 js 文件读取进来,把代码读取到我们的字符串里面,这样一方面方便我们管理,另一方面也可以直接通过代码检测自动补全功能,使用起来会比较方便。 然后,这里我们有一个小技巧,我们可以通过 format 字符串拼接的形式,将 Python 中的变量,也就是上面的变量 c 然后将这个变量写入到 Js 代码中,从而变相的实现了通过调用 JS 函数,在没有参数的情况下修改 JS 代码中的特定变量的值。最后我们拼接好了我我们的 JS 代码(add 和 script)。 拼完 JS 代码之后,我们这边再常规的进行一个操作,调用 Call 方法执行 aesEncrypt 这样一个函数,需要注意的是,这个代码里面 return 出来的 JS,它是一个 object,JS 中的 object 也就是 Python 中的字典。
我们实际使用时,如果需要在 Python 中拿到 object 的话,建议把它转换成一个 json 字符串,而不是直接的把结果 return 出来。 因为,有些时候 PyExecjs 对 object 的转换会出现问题,所以我们可能会拿到一些类似于将字典直接用 str 函数包裹后转为字符串的一个东西,这样的话它是无法通过正常的方式去解析的。 或者说你也可能会遇到其情况的报错,总之大家最好先转一下 json 字符串,然后再 return 避免踩坑。这是我们的一个代码。 接下来我们来说一下,PyExecJS 存在的一些问题主要有以下两点:
- 执行大型 JS 时会有点慢(这个是因为,每次执行 JS 代码的时候,都是从命令行去调用到的 JS,所以 JS 代码越复杂的话,nodejs 的初始化时间就越长,这个基本上是无解的)
- 特殊编码的输入或输出参数会出现报错的情况(因为,是从命令行调用的,所以在碰到一些特殊字符输入或输出参数或者 JS 代码本身就有一些特殊字符的情况下,就会直接执行不了,给你抛出一个异常。不过这个跟系统的命令行默认编码有一定关系,具体的话这里就不深究了,直接就说解决方案吧。)
- 可以把输入或输出的参数使用 Base64 编码一下(如果看报错是 JS 代码部分导致的,那就去看看能不能删除代码中的那部分字符或者你自己 new 一个上下文对象,将那个名叫 tempfile 的参数打开,这样在调用的时候,它就直接去执行那个文件了,不过大量调用的情况下,可能会对磁盘造成一定压力。
而如果参数不充分导致的话,有个很简单的方法:就是把参数使用 Base64 编码一下,因为编码之后出来的字符串,我们知道 Base64 编码之后是生成英文和数字组成的。这样就没有特殊符号了。所以就不会出现问题了。) 关于 PyExecejs 的相关东西就介绍到这里了,我们来看一些其他的内容。
3.5 其他使用 Python 调用 JS 的骚操作
前面说的都是非浏览器环境下直接调用 JS 的操作,但是还有一些市面上根本没人提到的骚操作,其实也挺好用的,接下来我给大家介绍一下:
- Selenium
- 一个 web 自动化测试框架,可以驱动各种浏览器进行模拟人工操作
- 用于渲染页面以方便提取数据或过验证码
- 也可以直接驱动浏览器执行 JS
这个大家是比较熟悉的,它是一个外部自动化的测试框架,可以驱动各种浏览器进行模拟人工操作,很多文章或者培训班的课程,都会提到它在爬虫方面的一个使用,比如用它采集一些动态页面,或者用来过一些滑动验证码之类的。 不过我们这里不用它来做这些事,我们要做的是用它来执行 JS 代码,因为这样的话是直接在浏览器环境下执行的 ,所以的话它是省了很多事,那么 Selenium 执行 JS 的核心代码,实际上就下面一行:
1 |
js = "一大段 JS" |
我们来看一下实际的例子: SeleniumDemo 进入项目根目录,输入:python server.py
1 |
$ python server.py |
访问 localhost:5002 我们进入网页之后,有这样的一句话:

每次刷新都会显示不同的内容,查看源代码的话,会发现这个页面中的源代码里面没有对应页面显示的那句话,而是只有一个 input 标签。
我还能观察到,input 标签里面有两个属性,一个是 id、一个是 data,这两个是比较关键的属性,然后我们还发现这里面引用了一个 js 文件,所以这个网页最终结果实际上是通过 JS 文件,然后一系列的操作生成的,那接下来我就来看看 JS 文件,做了什么工作。 js 我们可以看见,这个 JS 文件最后一句,有一个 window.onload =doit 的这样一代码,这个我们知道,当页面加载完成之后,立即执行这个 JS 方法。
1 |
function doit() { |
然后这个方法里面做了一个这样一个操作:let browser_type=BrowserType(); 首先去判断 supporter 是否等于 Chrome 这个 supporter 实际上有一个 browser_type 这个 browser_type 实际上就是检测浏览器等一系列参数,然后我们获取它里面的 supporter 属性,当 supporter( supporter =browser_type.supporter )等于 Chrome 的时候,我们再去执行这个 run 函数。
1 |
run: function (id, attr,supporter) { |
也就是 run 函数里面做了一系列操作,然后我传入的 id 可以通过看一下上面的函数 doit 可知传入的是 Base64 也就是说,实际上对 input 这个标签做了一个取值的操作,然后到这边我们就这整体一个过程将会用 JS 去模拟,所以这边我就不细说了。 最终会把这样的一个结果去通过 input.value 属性把值复制到 input 中,也就是我们最终看到的那样一个结果,到目前我就把这个 js 大概做了一件什么样的事情就已经讲的差不多了。接下来我们去看一下 Selenium 这边。 代码如下:
1 |
# -*- coding: utf-8 -*- |
这边关键的一行代码是:通过 execute_script(get_text("base64","data")) 这样的一句话去执行这个函数,这个函数实际上就是返回一段 JS 代码,这边实际上就是去模拟构造 run 所需要的一些参数,然后把最终的结果返回回去。 这里有两点需要注意:
- 如果里面存在拼接字符串的时候,注意花括号实际上要写两个
- 如果需要在后面需要获取 JS 返回的值,所以我们上面的代码需要加上 return 来返回 run 函数的结果
我们可以运行一下代码,输出结果如下:
1 |
$ python demo.py |
我们可以看到,我们程够获取到了结果。 这个例子因为它用到了检测浏览器的属性,而且它检测完属性之后会把属性值一直往下传,我们可以从上面的代码中看到它有很多地方使用。 所以,如果我们用 PyExecjs 来写的话,就需要修改很多参数,这样就很不方便了。因为我们需要去模拟这些浏览器参数,我这边写的例子比较简单,像那种更加复杂的。像获取更多的浏览器的一个属性的话,用 PyExecjs 再去写的时候,可能没有浏览器这样的一个环境,所以 PyExecjs 没有 Selenium 有优势。 当然,除了 Selenium 以为,还有一个叫做 Pyppeteer 的库,也是比较常见。 为了控制文章篇幅,咱们下次再续咯,记得关注公众号:AI悦创!





在 console 里面打印一下 Object(u.a)(e.encrypt_data) 初一看,好像是又好像不是(仅有部分信息)
没错,就是它。老板,求解密一下? ok,感谢老板。再次在 console 里面打印一下 Object(u.a)(e.encrypt_data) 当当当~
ok,那它是怎么来的呢?
当当当~,扣它,把这个函数扣出来(快到我怀里来~)
到这里就基本上把主函数弄完了,但是还没有完 a.a.decode(t)这个鬼我们还不晓得,进去找他,扣它 

完成!


encrypt:加密函数,b.val 加密对象(输入的密码)
将其扣出来! 为什么扣这里?因为这里为加密处!由明文转为密文。那我们拿到这些就以为着拿到了加密的函数。就可以自己实现加密
新问题:p.RSAKey;没有定义;回到 chrome 进入 p.RSAKey-(选中点击进入 f db())
进入 f db()扣出这个方法,然后改写 寻找 a.result.modulus, a.result.publicExponent 两个参数, 其实是 publickey 包返回的结果那么至此enpassword加密完成 补两个环境参数
link480 下断点点击下一步,运行 运行一步, 进入RSAfingerPrint函数内,把 o.page.RSAfingerPrint 方法抠出来 在页面中观察 a,b 参数
观察发现: 其实 a,b,就是我们的a.result.modulus, a.result.publicExponent,


看到这里面有很多链接,就是一些页面导航集合,这个页面就是列表页。 然后我们随便点开一篇新闻报道,如图所示:
这里就是一篇新闻报道,带有醒目的标题、发布时间、正文等内容,这就是详情页。 现在我们要做的就是用一个算法来凭借 HTML 代码区分出来哪个是列表页,哪个是详情页。 最后的输入输出如下:
每个文件夹几百个就行了,数量不用太多,五花八门的页面混起来更好。
这里我截图下来一张图片,如图所示:
然后我们把这个图片声明成一个 Template 传入,示例如下:
大家可以点击任意一个网站来爬取练习。
上面是一些案例的效果,基本上是使用 Django + Vue.js 开发的,主题使用了红色调,整个案例平台风格比较统一。另外还有一些 App 也是类似的风格,大家可以自行下载体验试试。 当然这里面最主要的还是案例的功能,比如各种加密、反爬、检测等等。
优化: 在一次回头看看冒泡排序具体实现思路,将列表每两个相邻的数,如果前面比后面大,则交换这两个数,一趟排序完成后,则无序区减少一个数,有序区增加一个数。 如果无序区已经是有序的呢?按照代码执行流程可知, 如果前者比后者大,那么则两个交换位置。(假设为降序,前面为无序区,后面为有序区) 否则不执行任何交换操作,但会执行便利(也可以理解为此运算”不执行任何交换操作,无实际意义”) 优化目标:(将“不执行任何交换的操作去掉”),咱们在回头看看,具体实际的运算是在第二层for循环里面的,也就说所谓的“无用功”也是在这里产生的 无用功体现为:无论是否进行了位置交换,都会在往有序区在遍历检查一遍 思路如下: 主要优化的地方在跳出循环,在它不交换位置的时候,直接跳出此次的循环 假设它全部都是有序的,并设个标记True, 当如果循环内发生了位置交换,则改变标记为False。 流程控制,if。当if True的时则会执行if内部代码(设立return,或者break)主要跳出循环。避免对有序区进行有一次的排序操作 具体代码实现如下:

需求如下:累计求和 1-n 的值(1. 为防止误差,验证 10 次; 2. 验证每次计算次数)
任意点开一篇新闻,看到的结果如下:
我现在需要做到的是在不编写任何 XPath、Selector 的情况下实现下面信息的提取: 对于列表页来说,我要提取新闻的所有标题列表和对应的链接,它们就是图中的红色区域:
这里红色区域分了多个区块,比如这里一共就是 40 个链接,我都需要提取出来,包括标题的名称,标题的 URL。 我们看到页面里面还有很多无用的链接,如上图绿色区域,包括分类、内部导航等,这些需要排除掉。 对于详情页,我主要关心的内容有标题、发布时间、正文内容,它们就是图中红色区域:
其中这里也带有一些干扰项,比如绿色区域的侧边栏的内容,无用的分享链接等。 总之,我想实现某种算法,实现如上两大部分的智能化提取。
然后编写提取代码如下:
编写测试代码如下:
后面会有大规模测试和修正。 项目初版,肯定存在很多不足,希望大家可以多发 Issue 和提 PR。 另外这里建立了一个 Gerapy 开发交流群,之前在 QQ 群的也欢迎加入,以后交流就在微信群了,大家在使用过程遇到关于 Gerapy、Gerapy Auto Extractor 的问题欢迎交流。 这里放一个临时二维码,后期可能会失效,失效后大家可以到公众号「进击的 Coder」获取加群方式。 

上面这行标题,没什么用,又这么难看。 我把偏好设置里面的显示内容都去掉了,设置如下:
但是它总是还显示了一个标题,显示成这个样子:
上面这个标题看得很难受,我想把它改成无任何内容,简洁清爽,如下图所示:
但是现在无论我怎么改偏好设置都不行,总会带上那些信息。 后来搜索了一番发现是 zsh 的问题。 打开
另外注意这里标题处不能完全为空,需要打上一个空格,否则窗口上方会显示「终端」二字。 最后在
完毕。









如果没有加入团队是没有权限向所相关的库进行推送的!!! 如何设置(获得)权限呢?(在仓库中点击设置选项进入如下界面) 
完成以上操作之后在进行推送即可有权限完成推送。



具体的流程可以参考上面的流程图:首先是 fork 一个仓库,然后拉去请求 后 clone 到本地,然后编辑更改。后推送到远程仓库(这里的克隆操作就省略了,具体的可以看上面)
发送即可完成。 然后接收者根据流程图步骤 6 开始操作即可
步骤如下:




版本前进 




系统用户级别的 config 是在系统目录下,如果不想太麻烦的去找直接 cat ~/.git config 即可
选择相对应的版本下载即可,下载完成后打开相对应的安装执行,有选项的选择的建议点击第一个默认配置,就不在此过多赘述啦。
以上的网页地址为:
Ubuntu:



经过一系列测试发现,其实际需操作的 URL 为
基本网站的分析就分析完毕了 注意此处为 POST 请求!!!
仔细经过上述步骤即可进入本次加密的源码详情页
搜索 sign 参数,得知本页面有 15 个 sign,筛选排查过后可得知以下位置为 sign 等参数,赋值加密过程 为什么会大概确定是此处呢? 理由一:var 声明赋值 理由二:md5() 为什么深信此处呢?
根据其语法可知,Javascript










这里一些接口的名称和 URL 我就打码了,这里我可以在 Grafana 中每时每刻都看到每个接口的可用率、响应(包括平均、最快、最慢)时间、状态码等信息,这些信息就是 JMeter 定时检测得到的结果,监控数据转到 Prometheus 里面然后经过 Grafana 可视化出来,并能通过一些指标来实现报警机制。 感兴趣的话,可以继续往下看哈。 为了达成这些功能,我需要解决如下问题:
这里提示几点可能用到的东西:
这里字段名如 jsr223_rt_as_summary 可以自行修改,比如这里我就统一修改为了 jmeter_test_xxx 这样的字段。 配置完成之后,运行 JMeter 之后,我们就能在
这里面就包含了 JMeter 的一些接口测试结果,包括成功次数、失败次数、状态码等等,另外还有 JVM、处理器等各种环境信息。 部署之后把对应的 URL 交由 Prometheus 就可以把监控数据收集到 Prometheus 里面了。
这里就能实时可视化展示出来错误率了,更多的一些配置可以自行修改这些表达式进行定制。 最后我配置成的一些监控面板如下所示:
这样我要是什么时候想看 Service 接口的情况,随时上来看就好了。
不过公司内部已经实现了一套了,对接了公司的员工账号,更加方便,所以我就没有再用这个了。
只需要给模型输入一张带缺口的验证码图片,模型就能输出缺口的轮廓和边界信息。 感兴趣的可以继续向下看具体的实现流程。
标注完了会生成一系列 xml 文件,你需要解析 xml 文件把位置的坐标和类别等处理一下,转成训练模型需要的数据。 在这里我先把我整理的数据集放出来吧,完整 GitHub 链接为:
val_mAP 变化如下:
可以看到 loss 从最初的非常高下降到了很低,准确率也逐渐接近 100%。 另外训练过程中还能看到如下的输出结果:
这里我们可以看到,利用训练好的模型我们就成功识别出缺口的位置了,另外程序还会打印输出这个边框的中心点和宽高信息。 有了这个边界信息,我们再利用某些手段拖动滑块即可通过验证了。本节不再展开讲解。





大家可以看到全站的内容都变成灰色了,包括按钮、图片等等。这时候我们可能会好奇这是怎么做到的呢? 有人会以为所有的内容都统一换了一个 CSS 样式,图片也全换成灰色的了,按钮等样式也统一换成了灰色样式。但你想想这个成本也太高了,而且万一某个控件忘记加灰色样式了岂不是太突兀了。 其实,解决方案很简单,只需要几行代码就能搞定了。
其 CSS 内容为:
果然是这个样式在起作用,而且是全局的效果,因为它是作用在了 html 这个节点之上的。 另外看看 CSDN,它也是用的这个 CSS 样式,其内容为:
比如这里通过 filter 样式改变了图片、颜色、模糊、对比度等等信息。 其所有用法示例如下:
再说回刚才的灰色图像,这里其实就是设置了 grayscale,其用法如下:
这里我们看到,这里除了 IE,其他的 PC、手机端的浏览器都支持了,Firefox 的 PC、安卓端还单独对 SVG 图像加了支持,可以放心使用。
接着我们点击 PyCharm 的 Tools -> Deployment -> Configuration,这里我们可以配置远程 SFTP 服务器,如图所示:
打开之后是这样子,这里选择 SFTP,然后填入服务器的连接信息,如图所示:
在这里可以点「TEST CONNECTION」测试下是否能够连接成功。 OK,配置完了之后,我们已经成功添加好了一台远程服务器了,比如我这里就添加了一台我自己的服务器,Host 为 vm1.cuiqingcai.com。 既然要实现本地和服务器文件同步,那么当然必须要指定本地项目文件夹和远程哪个文件夹同步吧。在哪里指定呢?切换到第二个选项卡,Mappings,如图所示:
这里我们可以通过选择 LocalPath 和 Deployment Path 分别指定本地和远程的文件夹名称。注意这里后者指的是相对服务器工作目录的路径。 好了,就是这样,基本配置就完成了。如果你还想配置某些路径不同步的话,还可以在第三个选项卡 Excluded Paths 里面配置。 接着,还有一些可以配置的地方,点击 Tools -> Deployment -> Options 我们可以配置更多细节,如图所示:
比如这里我就配置了下什么时候上传,这里我改成了按 Ctrl + S 保存的时候再上传,这样我可以自由控制上传的时机。 另外这里还需要把自动上传勾选上,如图所示:
好了,整个都配置好啦。
这样就上传完毕了。 接着我们任意修改一个文件,按保存,即 Ctrl + S,这里就出现了自动上传的日志,提示某个文件被上传成功了。
OK,验证没问题。
点了之后就会提示选择哪个远程服务器,选了之后,下方 Terminal 就弹出来了,和普通的 SSH Shell 一模一样。
OK,接下来要构建镜像,我只需要运行对应的 docker-compose 命令就好了,速度瞬间就上来了,我再也不用看着龟速的下拉速度而发愁了,而不用担心本地机器的资源消耗了。
OK,美滋滋。 构建完了运行之后,直接远程访问就好了。