Python基于execjs运行js过程解析


Posted in Python onNovember 27, 2020

execjs 使用

有了selenium+Chrome Headless 加载页面为什么还要用execjs来运行js?

selenium+Chrome Headless 必然是爬虫的一大利器,可是缺点依然存在, 性能问题不可忽视。

但这构不成舍弃它而不用的理由。我认为舍弃包括Chrome Headless、PhantomJS在内的无头浏览器的原因主要有以下几点:

1. 页面结构改变、弹窗(一些网站的页面结构经常无规则改变), 影响代码的健壮性。

2. 无头浏览器的应用场景主要是一些模拟登陆账号密码加密的场景, 爬虫全程使用无头浏览器, 影响性能和效率, 浪费资源。

3. 通过js加密的网站, 可以看得到加密过程,可以拿得到加密源码。

1. 安装

pip install PyExecJS # 需要注意, 包的名称:PyExecJS

2. 简单使用

import execjs
execjs.eval("new Date")

返回值为: 2018-04-04T12:53:17.759Z

execjs.eval("Date.now()")

返回值为:1522847001080 # 需要注意的是返回值是13位, 区别于python的time.time()

需要注意的是: 个别的JS语句, 用execjs返回的结果跟浏览器环境返回的结果是有区别的, 以下是浏览器环境返回的结果
浏览器环境运行的结果

Python基于execjs运行js过程解析

3. 调用函数

# 实际生产中处理的js有几百几千行, 不方便贴上来。来看一下源码中给的例子:
 ctx = execjs.compile("""
    function add(x, y) {
        return x + y;
      }
""")
 ctx.call("add", 1, 2) # 第一个参数 “add” 为JS函数名的字符串, 后边依次为实参
 返回值:3

execjs的用法非常简单, 下边来看一下执行JS的环境, 以及性能:

4. 执行JS的环境

# 1. 在windows上不需要其他的依赖便可运行execjs, 也可以调用其他的JS环境
  # windows 默认的执行JS的环境
    execjs.get().name
    返回值: JScript
  # 作者本人的windows上装有Node.js , 所以返回值不同
   execjs.get().name
   返回值: Node.js (V8)

#2. 在ubuntu下需要安装执行JS环境依赖, 作者的环境为PhantomJS
    execjs.get().name
    返回值: PhantomJS

#3. 源码中给出, 可执行execjs的环境:
 PyV8      = "PyV8"
 Node      = "Node"
 JavaScriptCore = "JavaScriptCore"
 SpiderMonkey  = "SpiderMonkey"
 JScript    = "JScript"
 PhantomJS   = "PhantomJS"
 SlimerJS    = "SlimerJS"
 Nashorn    = "Nashorn"

注1:作者之前在ubuntu环境下执行execjs碰见过因为没有环境而报错,因时间久远,无法肯定。 现在环境齐全, 报错无法复原,如有读者出现错误, 请留言, 多谢!

更新注1:经过朋友老冀的指正(在此感谢),在ubuntu环境下, 没有JS环境会报错:Could not find an available JavaScript runtime. 由此可见, execjs在ubuntu需要安装JS环境 。具体的JS环境需根据具体的需求安装, 切不可超过以上8种。

5.环境切换

# 1. 通过os.environ
  os.environ["EXECJS_RUNTIME"] = "Node"
  execjs.get().name
  execjs.eval("1 + 2")
  # 2. 通过execjs.get 切换
   jscript = execjs.get(execjs.runtime_names.JScript) # runtime_names 便是execjs源码中给出的执行环境的。 execjs.runtime_names.xxx xxx必须在上一节 #3中取
   jscript.eval("1 + 2")

注: 在切换环境时, 当环境不存在不会报错, 会使用默认的环境。 另外需要注意的是, 两种方式的区别

6. 简易性能分析

# 作者只简单试了三种, 在windows下
import execjs
import os
import time

# 先用JScript
os.environ["EXECJS_RUNTIME"] = "JScript"
print execjs.get().name

time1 = time.time()
for i in range(100):
  execjs.eval("new Date")
print time.time() - time1

# 切换环境 使用Nodejs
os.environ["EXECJS_RUNTIME"] = "Node"
print execjs.get().name

time2 = time.time()
for l in range(100):
  execjs.eval("new Date")
print time.time() - time2

# 打印的结果为:
JScript
4.70900011063
Node.js (V8)
27.501999855

# 在ubuntu下试的是PhantoJS , 结果竟然高达 30+ S

此注释来自execjs作者:PyExecJS的缺点之一就是性能。PyExecJS通过文本传递JavaScript运行时,并且速度很慢。另一个缺点是它不完全支持运行时特定的功能。对于某些用例,PyV8可能是更好的选择。

总注:使用execjs的难点并不是在execjs这个库, 而是解析JS的过程, 因为没有浏览器的环境, 没有加密源码的依赖。从成千上万行的JS中择出想要的内容,可能是一段孤零零的JS函数,也可能是从几个JS文件去找出各自找出一段JS代码, 并可以通过execjs顺利执行, 这并非易事。 需要慢慢积累经验。 一旦掌握, 便可以提高爬虫的效率, 以及代码的健壮性, 节省资源!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python+Django在windows下的开发环境配置图解
Nov 11 Python
Python中List.index()方法的使用教程
May 20 Python
正确理解python中的关键字“with”与上下文管理器
Apr 21 Python
python3+PyQt5实现自定义窗口部件Counters
Apr 20 Python
Python scrapy增量爬取实例及实现过程解析
Dec 24 Python
Python中的X[:,0]、X[:,1]、X[:,:,0]、X[:,:,1]、X[:,m:n]和X[:,:,m:n]
Feb 13 Python
使用Python 自动生成 Word 文档的教程
Feb 13 Python
python简单的三元一次方程求解实例
Apr 02 Python
Django websocket原理及功能实现代码
Nov 14 Python
python 如何用map()函数创建多线程任务
Apr 07 Python
python基础之while循环语句的使用
Apr 20 Python
Python编解码问题及文本文件处理方法详解
Jun 20 Python
celery在python爬虫中定时操作实例讲解
Nov 27 #Python
python输出国际象棋棋盘的实例分享
Nov 26 #Python
Django多个app urls配置代码实例
Nov 26 #Python
python Xpath语法的使用
Nov 26 #Python
python模拟点击玩游戏的实例讲解
Nov 26 #Python
Python批量修改xml的坐标值全部转为整数的实例代码
Nov 26 #Python
Django filter动态过滤与排序实现过程解析
Nov 26 #Python
You might like
PHP_MySQL教程-第一天
2007/03/18 PHP
PHP CURL模拟GET及POST函数代码
2010/04/25 PHP
PHP 查找字符串常用函数介绍
2012/06/07 PHP
解析用PHP实现var_export的详细介绍
2013/06/20 PHP
php使用pdo连接mssql server数据库实例
2014/12/25 PHP
php简单日历函数
2015/10/28 PHP
Symfony2安装第三方Bundles实例详解
2016/02/04 PHP
PHP+MySQL高并发加锁事务处理问题解决方法
2018/04/30 PHP
jQuery之排序组件的深入解析
2013/06/19 Javascript
Ext中下拉列表ComboBox组件store数据格式用法介绍
2013/07/15 Javascript
javascript中字符串的定义示例代码
2013/12/19 Javascript
input链接页面、打开新网页等等的具体实现
2013/12/30 Javascript
js和jquery设置disabled属性为true使按钮失效
2014/08/07 Javascript
创建js对象和js类的方法汇总
2014/12/24 Javascript
jQuery Validation Plugin验证插件手动验证
2016/01/26 Javascript
利用Angular.js限制textarea输入的字数
2016/10/20 Javascript
如何解决jQuery EasyUI 已打开Tab重新加载问题
2016/12/19 Javascript
node.js 中间件express-session使用详解
2017/05/20 Javascript
Angularjs自定义指令实现分页插件(DEMO)
2017/09/16 Javascript
解析vue中的$mount
2017/12/21 Javascript
[03:00]《DAC最前线》之欧美新秀VS老将
2015/02/01 DOTA
[01:02:45]完美世界DOTA2联赛 LBZS vs Forest 第三场 11.07
2020/11/09 DOTA
Python多线程threading和multiprocessing模块实例解析
2018/01/29 Python
numpy中实现二维数组按照某列、某行排序的方法
2018/04/04 Python
利用python的socket发送http(s)请求方法示例
2018/05/07 Python
python爬虫之自动登录与验证码识别
2020/06/15 Python
Python 实现Windows开机运行某软件的方法
2018/10/14 Python
Python和Java的语法对比分析语法简洁上python的确完美胜出
2019/05/10 Python
python批量生成身份证号到Excel的两种方法实例
2021/01/14 Python
学校办公室主任职责
2013/12/27 职场文书
关于工资低的辞职信
2014/01/14 职场文书
白酒市场营销方案
2014/02/25 职场文书
求职简历自我评价怎么写
2015/03/10 职场文书
2016年度优秀辅导员事迹材料
2016/02/26 职场文书
2019最新企业员工考勤管理制度(通用版)!
2019/07/02 职场文书
盘点2020年适合农村地区创业的项目
2019/10/16 职场文书