python 调用js的四种方式


Posted in Python onApril 11, 2021

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)

更多功能可以参考:

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

7. 最后

上面总结了 Python 调用 JS 的 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的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python实现周期性抓取网页内容的方法
Nov 04 Python
Python类属性的延迟计算
Oct 22 Python
python通过getopt模块如何获取执行的命令参数详解
Dec 29 Python
python八皇后问题的解决方法
Sep 27 Python
Python3实现统计单词表中每个字母出现频率的方法示例
Jan 28 Python
django 捕获异常和日志系统过程详解
Jul 18 Python
python并发编程多进程 互斥锁原理解析
Aug 20 Python
python openCV获取人脸部分并存储功能
Aug 28 Python
浅谈OpenCV中的新函数connectedComponentsWithStats用法
Jul 05 Python
详解python3类型注释annotations实用案例
Jan 20 Python
简述python四种分词工具,盘点哪个更好用?
Apr 13 Python
Python制作春联的示例代码
Jan 22 Python
Python WSGI 规范简介
使用pytorch实现线性回归
pytorch实现线性回归以及多元回归
python如何获取网络数据
Apr 11 #Python
Pytorch 使用tensor特定条件判断索引
selenium.webdriver中add_argument方法常用参数表
Apr 08 #Python
python3使用diagrams绘制架构图的步骤
You might like
2020年4月放送!《Princess Connect Re:Dive》制作组 & 角色声优公开!
2020/03/06 日漫
php MsSql server时遇到的中文编码问题
2009/06/11 PHP
使用JSON实现数据的跨域传输的php代码
2011/12/20 PHP
基于empty函数的判断详解
2013/06/17 PHP
在PHP中使用redis
2013/11/04 PHP
php中动态修改ini配置
2014/10/14 PHP
php+ajax无刷新分页实例详解
2015/12/07 PHP
php使用文本统计访问量的方法
2016/05/12 PHP
如何使用php等比例缩放图片
2016/10/12 PHP
PHP常用字符串函数用法实例总结
2020/06/04 PHP
ajax的hide隐藏问题解决方法
2012/12/11 Javascript
jquery实现多屏多图焦点图切换特效的方法
2015/05/04 Javascript
JavaScript实现跨浏览器的添加及删除事件绑定函数实例
2015/08/04 Javascript
基于jQuery实现带动画效果超炫酷的弹出对话框(附源码下载)
2016/02/22 Javascript
seajs学习之模块的依赖加载及模块API的导出
2016/10/20 Javascript
基于JavaScript实现的插入排序算法分析
2017/04/14 Javascript
JavaScript实现多态和继承的封装操作示例
2018/08/20 Javascript
JS判断两个数组或对象是否相同的方法示例
2019/02/28 Javascript
nodejs中各种加密算法的实现详解
2019/07/11 NodeJs
浅谈JavaScript节流和防抖函数
2020/08/25 Javascript
python操作CouchDB的方法
2014/10/08 Python
Python编程中的文件操作攻略
2015/10/16 Python
在python里创建一个任务(Task)实例
2020/04/25 Python
解决django migrate报错ORA-02000: missing ALWAYS keyword
2020/07/02 Python
浅析Python迭代器的高级用法
2020/07/16 Python
python Matplotlib模块的使用
2020/09/16 Python
快速创建 HTML5 Canvas 电信网络拓扑图的示例代码
2018/03/21 HTML / CSS
网站性能延迟加载图像的五种技巧(小结)
2020/08/13 HTML / CSS
学历公证书范本
2014/04/09 职场文书
学校安全责任书
2014/04/14 职场文书
学生无故旷课检讨书
2014/09/20 职场文书
2014年综治维稳工作总结
2014/11/17 职场文书
高中班主任评语
2014/12/30 职场文书
工作失职检讨书
2015/01/26 职场文书
《初涉尘世》读后感3篇
2020/01/10 职场文书
Python实现提取PDF简历信息并存入Excel
2022/04/02 Python