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 10 Python
Python ORM框架SQLAlchemy学习笔记之数据查询实例
Jun 10 Python
合并百度影音的离线数据( with python 2.3)
Aug 04 Python
python实现随机调用一个浏览器打开网页
Apr 21 Python
python字符串常用方法
Jun 14 Python
django使用LDAP验证的方法示例
Dec 10 Python
python接口自动化测试之接口数据依赖的实现方法
Apr 26 Python
pyenv与virtualenv安装实现python多版本多项目管理
Aug 17 Python
Python调用Windows API函数编写录音机和音乐播放器功能
Jan 05 Python
Python3.x+pyqtgraph实现数据可视化教程
Mar 14 Python
Django-migrate报错问题解决方案
Apr 21 Python
Python实现打包成库供别的模块调用
Jul 13 Python
Python WSGI 规范简介
使用pytorch实现线性回归
pytorch实现线性回归以及多元回归
python如何获取网络数据
Apr 11 #Python
Pytorch 使用tensor特定条件判断索引
selenium.webdriver中add_argument方法常用参数表
Apr 08 #Python
python3使用diagrams绘制架构图的步骤
You might like
PHP判断变量是否为0的方法
2014/02/08 PHP
从PHP的源码中深入了解stdClass类
2014/04/18 PHP
PHP自带ZIP压缩、解压缩类ZipArchiv使用指南
2015/03/03 PHP
详解PHP如何更好的利用PHPstorm的自动提示
2017/08/18 PHP
php的lavarel框架中join和orWhere的用法
2020/12/28 PHP
JS 实现点击a标签的时候让其背景更换
2013/10/15 Javascript
在页面中js获取光标/鼠标的坐标及光标的像素坐标
2013/11/11 Javascript
jQuery实现瀑布流的取巧做法分享
2015/01/12 Javascript
JQuery中使文本框获得焦点的方法实例分析
2015/02/28 Javascript
纯javascript实现四方向文本无缝滚动效果
2015/06/16 Javascript
详解javascript事件冒泡
2016/01/09 Javascript
原生js实现倒计时--2018
2017/02/21 Javascript
Node.js 使用命令行工具检查更新
2017/06/08 Javascript
JavaScript实现的拼图算法分析
2019/02/13 Javascript
vue设计一个倒计时秒杀的组件详解
2019/04/06 Javascript
python with statement 进行文件操作指南
2014/08/22 Python
python使用BeautifulSoup分析网页信息的方法
2015/04/04 Python
在Python的setuptools框架下生成egg的教程
2015/04/13 Python
最近Python有点火? 给你7个学习它的理由!
2017/06/26 Python
python分别打包出32位和64位应用程序
2020/02/18 Python
python之生成多层json结构的实现
2020/02/27 Python
动态设置django的model field的默认值操作步骤
2020/03/30 Python
tensorflow实现残差网络方式(mnist数据集)
2020/05/26 Python
idea2020手动安装python插件的实现方法
2020/07/17 Python
java关于string最常出现的面试题整理
2021/01/18 Python
Linux系统下升级pip的完整步骤
2021/01/31 Python
美国最大的网上冲印店:Shutterfly
2017/01/01 全球购物
htmlentities() 和 htmlspecialchars()有什么区别
2015/07/01 面试题
Linux内核产生并发的原因
2016/11/08 面试题
社区七一党员活动方案
2014/01/25 职场文书
银行见习期自我鉴定
2014/01/29 职场文书
预备党员2014全国两会学习心得体会
2014/03/10 职场文书
意外死亡赔偿协议书
2014/10/14 职场文书
销售开票员岗位职责
2015/04/15 职场文书
2015年学校工作总结范文
2015/04/20 职场文书
初中地理教学反思
2016/02/19 职场文书