最全总结!聊聊 Python 调用 JS 的几种方式

微信扫一扫,分享到朋友圈

最全总结!聊聊 Python 调用 JS 的几种方式

点击上方“ AirPython ”,选择“ 加为星标

第一时间关注 Python 技术干货!

1. 前言

日常 Web 端爬虫过程中,经常会遇到参数被加密的场景,因此,我们需要分析网页源代码

通过调式,一层层剥离出关键的 JS 代码,使用 Python 去执行这段代码,得出参数加密前后的 Python 实现

本文将聊聊利用 Python 调用 JS 的 4 种方式

2. 准备

以一段简单的 JS 脚本为例,将代码写入到文件中

//norm.js
//计算两个数的和
function add(num1, num2) {
return num1 + num2;
}

其中,定义了一个方法,计算两个数的和

3. 方式一:PyExecJS

PyExecJS 是使用最多的一种方式,底层 实现方式是: 在本地 JS 环境下运行 JS 代码

支持的 JS 环境包含:Node.js、PyV8、PhantomJS、Nashorn 等

首先,我们需要安装依赖包 PyExecJS

//py_exec_js_demo.py
//安装依赖
pip3 install PyExecJS

然后,从 JS 文件中读取源码

def js_from_file(file_name):
"""
读取js文件
:return:
"""
with open(file_name, 'r', encoding='UTF-8') as file:
result = file.read()
return result

最后,使用 execjs 类的 compile() 方法编译加载上面的 JS 字符串,返回一个上下文对象

import execjs
from js_code import *
# 编译加载js字符串
context1 = execjs.compile(js_from_file('./norm.js'))

最后,调用上下文对象的 call()  方法执行 JS 方法

其中,参数包含:JS 代码被调的方法名、对应方法的传入参数

# 调用js代码中的add()方法,参数为2和3
# 方法名:add
# 参数:2和3
result1 = context1.call("add", 2, 3)
print(result1)

需要注意的, 由于 PyExecJS 运行在本地 JS 环境下,使用之前会启动 JS 环境,最终导致运行速度会偏慢

更多功能可以参考:

https://github.com/doloopwhile/PyExecJS

4. 方式二:js2py

js2py
作为一个纯 Python 实现的 JS 解释器,可以完全脱离 JS 环境,直接将 JS 代码转换为 Python 代码

首先,安装依赖库

# 安装依赖库
pip3 install js2py

然后使用 js2py 中的 EvalJs() 方法生成一个上下文对象

# 使用获取上下js2py生成一个上下文环境
context = js2py.EvalJs()

接着利用上下文对象执行 JS 脚本,转换为 Python 代码

# 执行整段JS代码
context.execute(js_content)

最后,利用上下文调用 JS 中的方法,并制定输入参数即可

# 使用上下文context调用具体的函数
# 函数名:add
# 参数:1,2
result = context.add(1, 2)
print(result)

需要注意是, 如果 JS 是很长的混淆代码,转换为 Python 的过程可能会报错

更多功能可以参考:

https://github.com/PiotrDabkowski/Js2Py

5. 方式三:Node.js

实际上是使用 Python 的 os.popen 执行 node 命令,执行 JS 脚本

首先,确保本地已经安装了 Node.js 环境

修改 JS 脚本,新增一个导出函数 init ,方便内部函数被调用

//计算两个数的和
function add(num1, num2) {
return num1 + num2;
}
//新增一个导出函数(node方式)
module.exports.init = function (arg1, arg2) {
//调用函数,并返回
console.log(add(arg1, arg2));
};

然后,将调用 JS 方法的命令组成一个字符串

# 组成调用js的命令
# node命令:node -e
cmd = 'node -e "require(\\"%s\\").init(%s,%s)"' % ('./norm', 3, 5)

最后,通过 os.popen 执行命令即可

pipeline = os.popen(cmd)
# 读取结果
result = pipeline.read()
print('结果是:', result)

6. 方式四:PyV8

PyV8 是 Google 将 Chrome V8 引擎用 Python 封装的依赖库

它不依赖本地 JS 环境,运行速度很快

import PyV8
from js_code import js_from_file
with PyV8.JSContext() as ctx:
ctx.eval(js_from_file('./norm.js'))
# 调用js函数,指定参数
ctx.locals.add(1, 2)

但是经过反复测试发现, MAC 和 PC 在 Python3 环境下,使用 PyV8 会报各种奇怪的问题,所以不推荐使用!

更多功能可以参考:

https://github.com/emmetio/pyv8-binaries

7. 最后

上面总结了 Python 调用 JS 的 4 种方式

实际爬虫项目中, 一般会先使用 node 命令进行一次测试,确保没问题后,再使用前 3 种方式的任意一种进行 Python 改写

我已经将文中全部源码上传到后台,关注公众号后回复「  pjs  」即可获得全部源码

如果你觉得文章还不错,请大家  点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!

留言送书

本周赠书:《 Python编程300例——快速构建可执行高质量代码

PS: 中奖名单将于下周一在交流群/朋友圈同步公布

推荐阅读

如何结合爬虫与自动化,帮助小姐姐刷抖音完全解放掉双手

最全总结!聊聊 Python 发送邮件的几种方式

聊聊 Python 代码覆盖率工具 – Coverage

微信扫一扫,分享到朋友圈

最全总结!聊聊 Python 调用 JS 的几种方式

Flask(数据库操作 十一)

上一篇

效率提升之道:9大Jupyter Notebook扩展工具

下一篇

你也可能喜欢

最全总结!聊聊 Python 调用 JS 的几种方式

长按储存图像,分享给朋友