Python 执行 js 的处理方法

爬虫开发中经常会遇到 js 反爬,为应对反爬,最快的方法就是在 python 中直接执行 js 获取结果。

常用的第三方库有:js2py、execjs、pyv8

第三方库 使用心得 项目状态 开源地址
Js2Py 速度较快,不支持 dom 维护中 https://github.com/PiotrDabkowski/Js2Py
PyExecJS 功能较全,性能较差 停止维护 https://github.com/doloopwhile/PyExecJS
pyv8 没用过 停止维护 https://github.com/emmetio/pyv8-binaries

1、Js2Py

1.1 工作原理

将 js 编译成 python 执行,优雅灵活,速度较快,但是部分功能暂时无法实现。

比如目前不支持 dom 操作,所以 js 中有 dom 操作的,可以先用 execjs 。

1.2 安装

pip install js2py

1.3 使用

import js2py

# 例1
js_text = """
function add(a, b) {return a + b}
"""
js = js2py.EvalJs()
js.execute(js_text)
total = js.add(11, 22)
print(total)

# 例2
js_text = """
c = base;
function add(a, b) {return a + b + c}
"""
js = js2py.EvalJs({'base': 100})
js.execute(js_text)
total = js.add(11, 22)
print(total, js.c)

2、PyExecJS

2.1 工作原理

PyExecJS 是来自 Ruby的 ExecJS 的移植。PyExecJS 通过文本传达 JavaScript 运行,并且运行缓慢。另一个缺点是它不完全支持运行时特定的功能。

依赖 node.js,但是比 Js2Py 支持的功能要全一些,比如 dom 支持。所以,目前可以作为 Js2Py 的一个补充工具,遇到一般 js 时,还是建议优先选择 Js2Py 。

2.2 安装

pip install PyExecJS

2.3 使用

import execjs

# 例1
js_text = """
'red yellow blue'.split(' ')
"""
t = execjs.eval(js_text)
print(t)

# 例2
js_text = """
t=100
function add(a, b) {return a + b}
"""
js = execjs.compile(js_text)  # 获取代码编译完成后的对象
total = js.call('add', 10, 20)
print(total)

3、Js 中含有 window, document 的处理

当 Js 中含有 window, document 时,就会报错了,这时就需要安装 jsdom 进行处理。

image-20201021171217564

3.1 需要安装 jsdom

执行安装命令后,会在当前路径下,生成一个文件夹 node_modules,后续将在 py 中引用。

需要注意路径,建议和当前的 py 脚本放在一个路径下

npm install jsdom

3.2 修改 js,引入 jsdom

在 js 代码前面,加入如下代码,用来调用 jsdom,引入 dom 对象

js_text = """
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
window = dom.window;
document = window.document;
XMLHttpRequest = window.XMLHttpRequest;

另外,这边需要把 atob 改为 window.atob,然后就 ok 了

import execjs

js_text = """
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
window = dom.window;
document = window.document;
XMLHttpRequest = window.XMLHttpRequest;

function add(a) {
document.e = 100
return window.atob(document.e + a)}
"""
js = execjs.compile(js_text, cwd='node_modules')  # 获取代码编译完成后的对象
total = js.call('add', 10)
print(total)

image-20201021175310290

版权声明:如无特殊说明,文章均为本站原创,转载请注明出处

本文链接:http://blog.turboway.top/article/PyExecJS/

许可协议:署名-非商业性使用 4.0 国际许可协议