Python 调用 JS 的四种主流方式详解
本文详细介绍Python调用JavaScript代码的四种常用方式。通过PyExecJS利用本地JS环境执行,js2py实现纯Python解释器转换,Node.js命令直接调用,以及PyV8封装Chrome V8引擎。文章对比了各方案的优缺点及适用场景,适用于Web爬虫参数加密逆向等实际需求。
1. 前言
在进行Web端爬虫开发时,经常遇到请求参数经过加密的情况。为了获取正确数据,必须深入分析网页源代码。
通过调试工具逐步剥离出关键的JavaScript逻辑,随后使用Python执行这段JS代码,从而复现参数加密前后的处理流程。
本文将重点探讨利用Python调用JavaScript代码的4种具体实现方式。
2. 准备
为了演示,我们准备一段简单的JavaScript脚本,并将其保存为文件。
//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)
更多功能可参考:
https://github.com/emmetio/pyv8-binaries
7. 最后
以上总结了Python调用JavaScript的4种主要方式。
在实际爬虫项目中,建议先使用node命令进行初步测试,确认逻辑无误后,再选择前3种方式中的任意一种进行Python代码改写。
示例代码地址:https://github.com/xingag/tools_python/tree/master/Python%E6%89%A7%E8%A1%8CJS%E6%80%BB%E7%BB%93
以上就是python 调用js的四种方式的详细内容,更多关于python 调用js的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













