调用JS代码的2种方式
使用Python调用JS
- PyV8
V8是Google开源的一个JavaScript引擎,被使用在了Chrome中。PyV8是V8引擎的一个Python层包装,可以用来调用V8引擎来执行JS代码。最新版本2010,已经年久失修,并且存在内存泄漏的问题,不推荐使用。
- Js2Py
Js2Py是一个纯Python实现的JavaScript解释器和翻译器。虽然2019年依然有更新,但是也是6月份的事情,而且它的issues里有很多的bug未修复(https://github.com/PiotrDabkowski/Js2Py/issues)。
解释器部分:性能不高且存在一些bug。翻译器部分:对于高度混淆的大型JS会转换失败,而且转换出来的代码可读性差,性能不高。不推荐使用。
- PyMiniRacer
同样是V8引擎的包装,和PyV8效果一样。一个继任PyExecJS和PyV8的库。而且是一个较新的库,不知道有什么坑。可以尝试。
- PyExecJS
一个最开始诞生于Ruby中的库,后来被移植到了Python上。有多个引擎可选,但一般我们会选择使用Node作为引擎执行代码。
缺点:执行大型JS时会有点慢,特殊编码的输入或输出参数会出现报错的情况(可以把输入或输出的参数使用Base64编码一下)。总体而言推荐使用
- Selenium
一个web自动化测试框架,可以驱动各种浏览器进行模拟人工操作。用于渲染页面以方便提取数据或过验证码。也可以用来执行JS代码。
- Pyppeteer
Puppeteer的Python版本,是第三方开发的,是一个Web自动化测试框架。原生支持以协程的方式调用,同时性能比Selenium更好。对于使用Asyncio+Aiohttp写爬虫的人而言可以直接使用。可以直接驱动浏览器来执行JS代码。
- Playwright
微软开发的Web自动化测试框架,有多种语言的版本,支持同步与异步两种方式,也可以直接驱动浏览器来执行JS代码。
总结:如果执行的JS不是特别复杂,且不依赖浏览器环境(比如需要读取浏览器相关属性)推荐使用PyExecJS,如果执行的JS是一个比较大的工程,或者使用过程中需要读取浏览器相关属性,这时候PyExecJS已经不能满足要求,推荐使用Playwright和Playwright。
PyExecJS使用
环境准备:推荐安装Nodejs,安装方便且执行效率高。然后通过pip install pyexecjs
来安装PyExecJS。
然后打开终端,执行下面2行代码:
1 | import execjs |
如果结果如下,证明PyExecJS使用的引擎是NodeJS:

如果不是,则需要手动配置一下使用的引擎,编辑系统环境变量设置如下变量即可:
1 | export EXECJS_RUNTIME="Node" |
配置好PyExecJS后,看一下使用代码实例:
1 | import execjs |
首先通过execjs的compile方法将js代码编译好之后保存在一个context中,然后调用context的call方法去执行js代码中的某一个function。
使用NodeJS调用JS
简单来说就是,提供一个可以执行JS的HTTP API,然后通过调用这个API来执行JS并获取想要的结果。
- 首先将要执行的JS单独封装成一个或者多个文件
1 | var add = function(a, b) { |
这里只是一个演示,实际可能是一段很复杂的代码逻辑。
- 然后使用Node搭建一个Express服务
1 | var express = require('express') |
- 最后Python客户端去调用这个服务,拿到JS代码执行之后的结果
1 | import requests |
这种方式存在的问题以及解决方案:
- Window对象
- NodeJS没有window对象,如果要使用window对象,需要自己创建一个或者指向global
- 使用jsdom之类的库去替代
看下面代码示例:
1 | // 1. 这些对象存在于js,而不存在于nodejs,比如window,document, screen |
- Base64
window.btoa在NodeJS中不存在,可以使用Buffer.from(“Python3”).toString(“base64”)来代替。