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中的元类(metaclass)
Feb 14 Python
用Python进行行为驱动开发的入门教程
Apr 23 Python
Python字典数据对象拆分的简单实现方法
Dec 05 Python
python实现用户管理系统
Jan 10 Python
5个很好的Python面试题问题答案及分析
Jan 19 Python
Python爬虫实现(伪)球迷速成
Jun 10 Python
如何优雅地改进Django中的模板碎片缓存详解
Jul 04 Python
使用Django和Postgres进行全文搜索的实例代码
Feb 13 Python
解决python中import文件夹下面py文件报错问题
Jun 01 Python
浅谈numpy中函数resize与reshape,ravel与flatten的区别
Jun 18 Python
python 字符串的驻留机制及优缺点
Jun 19 Python
python 如何做一个识别率百分百的OCR
May 29 Python
Python WSGI 规范简介
使用pytorch实现线性回归
pytorch实现线性回归以及多元回归
python如何获取网络数据
Apr 11 #Python
Pytorch 使用tensor特定条件判断索引
selenium.webdriver中add_argument方法常用参数表
Apr 08 #Python
python3使用diagrams绘制架构图的步骤
You might like
PHP为表单获取的URL 地址预设 http 字符串函数代码
2010/05/26 PHP
PHP数组函数知识汇总
2016/05/12 PHP
php变量与数组相互转换的方法(extract与compact)
2016/12/02 PHP
雄兵连第三季海报曝光,艾妮熙德成主角,蔷薇新造型
2021/03/09 国漫
Avengerls vs Newbee BO3 第一场2.18
2021/03/10 DOTA
JavaScript Event学习第四章 传统的事件注册模型
2010/02/07 Javascript
ExtJS4 组件化编程,动态加载,面向对象,Direct
2011/05/12 Javascript
jquery中防刷IP流量软件影响统计的一点对策
2011/07/10 Javascript
js原型链原理看图说明
2012/07/07 Javascript
最新最热最实用的15个jQuery插件汇总
2015/07/05 Javascript
Angular工具方法学习
2016/12/26 Javascript
使用prop解决一个checkbox选中后再次选中失效的问题
2017/07/05 Javascript
vue双花括号的使用方法 附练习题
2017/11/07 Javascript
angular.js和vue.js中实现函数去抖示例(debounce)
2018/01/18 Javascript
vue实现分页组件
2020/06/16 Javascript
js实现ATM机存取款功能
2020/10/27 Javascript
vue-router 起步步骤详解
2019/03/26 Javascript
vue缓存的keepalive页面刷新数据的方法
2019/04/23 Javascript
Python协程的用法和例子详解
2017/09/09 Python
python实现八大排序算法(1)
2017/09/14 Python
Python实现读写INI配置文件的方法示例
2018/06/09 Python
Python进阶:生成器 懒人版本的迭代器详解
2019/06/29 Python
python networkx 根据图的权重画图实现
2019/07/10 Python
Python学习笔记之lambda表达式用法详解
2019/08/08 Python
python3实现高效的端口扫描
2019/08/31 Python
Python笔试面试题小结
2019/09/07 Python
Python 按比例获取样本数据或执行任务的实现代码
2020/12/03 Python
美国在线奢侈品寄售商店:Luxury Garage Sale
2018/08/19 全球购物
历史专业毕业生的自我鉴定
2013/11/15 职场文书
感恩节红领巾广播稿
2014/02/11 职场文书
校园公益广告语
2014/03/13 职场文书
优秀三好学生事迹材料
2014/08/31 职场文书
2015中秋节晚会开场白
2015/07/30 职场文书
Win11局域网共享权限在哪里设置? Win11高级共享的设置技巧
2022/04/05 数码科技
SQL SERVER中的流程控制语句
2022/05/25 SQL Server
GoFrame gredis缓存DoVar Conn连接对象 自动序列化GoFrame gredisDo/DoVar方法Conn连接对象自动序列化/反序列化总结
2022/06/14 Golang