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和bash统计CPU利用率的方法
Jul 10 Python
python实现随机漫步算法
Aug 27 Python
浅谈python新式类和旧式类区别
Apr 26 Python
python时间序列按频率生成日期的方法
May 14 Python
Django REST framework内置路由用法
Jul 26 Python
Python基础之字典常见操作经典实例详解
Feb 26 Python
如何使用python切换hosts文件
Apr 29 Python
Python 为什么推荐蛇形命名法原因浅析
Jun 18 Python
Python数据可视化常用4大绘图库原理详解
Oct 23 Python
Python Selenium异常处理的实例分析
Feb 28 Python
Python中使用Lambda函数的5种用法
Apr 01 Python
Python-OpenCV教程之图像的位运算详解
Jun 21 Python
Python WSGI 规范简介
使用pytorch实现线性回归
pytorch实现线性回归以及多元回归
python如何获取网络数据
Apr 11 #Python
Pytorch 使用tensor特定条件判断索引
selenium.webdriver中add_argument方法常用参数表
Apr 08 #Python
python3使用diagrams绘制架构图的步骤
You might like
遍历指定目录下的所有目录和文件的php代码
2011/11/27 PHP
Php图像处理类代码分享
2012/01/19 PHP
PHP面向对象程序设计之类与反射API详解
2016/12/02 PHP
PHP中类的自动加载的方法
2017/03/17 PHP
PHP验证码无法显示的原因及解决办法
2017/08/11 PHP
总结PHP代码规范、流程规范、git规范
2018/06/18 PHP
PHP利用DWZ.CN服务生成短网址
2019/08/11 PHP
laravel框架使用极光推送消息操作示例
2020/02/15 PHP
web 页面分页打印的实现
2009/06/22 Javascript
JQuery 风格的HTML文本转义
2009/07/01 Javascript
关于javascript 回调函数中变量作用域的讨论
2009/09/11 Javascript
jWiard 基于JQuery的强大的向导控件介绍
2011/10/28 Javascript
JavaScript控制图片加载完成后调用回调函数的方法
2015/03/20 Javascript
JQuery中DOM实现事件移除的方法
2015/06/13 Javascript
javascript日期处理函数,性能优化批处理
2015/09/06 Javascript
AngularJS入门教程之链接与图片模板详解
2016/08/19 Javascript
jQuery实现的无缝广告图片左右滚动功能详解
2016/12/24 Javascript
node.js实现登录注册页面
2017/04/08 Javascript
基于 D3.js 绘制动态进度条的实例详解
2018/02/26 Javascript
[01:20]PWL S2开团时刻第三期——团战可以输 蝙蝠必须死
2020/11/26 DOTA
[01:00:10]完美世界DOTA2联赛PWL S2 FTD vs Inki 第二场 11.21
2020/11/24 DOTA
pygame游戏之旅 游戏中添加显示文字
2018/11/20 Python
python批量创建指定名称的文件夹
2019/03/21 Python
django框架实现一次性上传多个文件功能示例【批量上传】
2019/06/19 Python
Python Pandas数据结构简单介绍
2019/07/03 Python
Python 实现向word(docx)中输出
2020/02/13 Python
Python3批量创建Crowd用户并分配组
2020/05/20 Python
python与c语言的语法有哪些不一样的
2020/09/13 Python
Flask处理Web表单的实现方法
2021/01/31 Python
荷兰手表网站:Watch2Day
2018/07/02 全球购物
Nike香港官网:Nike HK
2019/03/23 全球购物
大学社团招新的通讯稿
2014/09/10 职场文书
夫妻分居协议书范文
2014/11/26 职场文书
幼师辞职信范文大全
2015/05/12 职场文书
Pyhton爬虫知识之正则表达式详解
2022/04/01 Python
关于对TypeScript泛型参数的默认值理解
2022/07/15 Javascript