Python基于execjs运行js过程解析

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返回的结果跟浏览器环境返回的结果是有区别的, 以下是浏览器环境返回的结果
浏览器环境运行的结果

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顺利执行, 这并非易事。 需要慢慢积累经验。 一旦掌握, 便可以提高爬虫的效率, 以及代码的健壮性, 节省资源!

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

(0)

相关推荐

  • Python利用PyExecJS库执行JS函数的案例分析

      在Web渗透流程的暴力登录场景和爬虫抓取场景中,经常会遇到一些登录表单用DES之类的加密方式来加密参数,也就是说,你不搞定这些前端加密,你的编写的脚本是不可能Login成功的.针对这个问题,现在有三种解决方式: ①看懂前端的加密流程,然后用脚本编写这些方法(或者找开源的源码),模拟这个加密的流程.缺点是:不懂JS的话,看懂的成本就比较高了: ②selenium + Chrome Headless.缺点是:因为是模拟点击,所以效率相对①.③低一些: ③使用语言调用JS引擎来执行JS函数.缺点是

  • Python中的exec、eval使用实例

    通过exec可以执行动态Python代码,类似Javascript的eval功能:而Python中的eval函数可以计算Python表达式,并返回结果(exec不返回结果,print(eval("-"))打印None): 复制代码 代码如下: >>> exec("print(\"hello, world\")") hello, world >>> a = 1 >>> exec("a

  • Python使用pyexecjs代码案例解析

    针对现在大部分的网站都是使用js加密,js加载的,并不能直接抓取出来,这时候就不得不适用一些三方类库来执行js语句 execjs,一个比较好用且容易上手的类库(支持py2,与py3),支持 JS runtime. 官网:https://pypi.org/project/PyExecJS/ # pip install pyexecjs # 一node.js为引擎 # 检测运行环境 import execjs print(execjs.get().name) 最简单的代码案例 使用eval执行js代

  • python爬虫 execjs安装配置及使用

    模块安装 参考官方文档安装 pip install PyExecJS 配置 该模块需要JS运行时环境 以下JS runtime经过官方测试认可,建议采用 PyV8:一个调用Google V8引擎的Python模块 Node.js 本文采用该运行时 PhantomJS Nashorn 以下JS runtime也支持但未经过官方测试 Apple JavaScriptCore - Included with Mac OS X JScript :windows自带JS解释器,IE浏览器 SlimerJS

  • python对execl 处理操作代码

    1. 读取execl 1.前提需要安装xlrd模块,这个在网上可以找安装教程,这里就不写了 2. 打开表格 3. 读取表格的sheet 4. 按行读取数据或者列读取数据或者单元格读取数据 实际操作: import xlrd import xlwt from xlutils.copy import copy def info_row_col_execl(file_name): myworkbook = xlrd.open_workbook(file_name) mySheetlist = mywo

  • 解决python ThreadPoolExecutor 线程池中的异常捕获问题

    问题 最近写了涉及线程池及线程的 python 脚本,运行过程中发现一个有趣的现象,线程池中的工作线程出现问题,引发了异常,但是主线程没有捕获异常,还在发现 BUG 之前一度以为线程池代码正常返回. 先说重点 这里主要想介绍 python concurrent.futuresthread.ThreadPoolExecutor 线程池中的 worker 引发异常的时候,并不会直接向上抛起异常,而是需要主线程通过调用concurrent.futures.Future.exception(timeou

  • Python基于execjs运行js过程解析

    execjs 使用 有了selenium+Chrome Headless 加载页面为什么还要用execjs来运行js? selenium+Chrome Headless 必然是爬虫的一大利器,可是缺点依然存在, 性能问题不可忽视. 但这构不成舍弃它而不用的理由.我认为舍弃包括Chrome Headless.PhantomJS在内的无头浏览器的原因主要有以下几点: 1. 页面结构改变.弹窗(一些网站的页面结构经常无规则改变), 影响代码的健壮性. 2. 无头浏览器的应用场景主要是一些模拟登陆账号密

  • SpringBoot基于数据库实现定时任务过程解析

    这篇文章主要介绍了SpringBoot基于数据库实现定时任务过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在我们平时开发的项目中,定时任务基本属于必不可少的功能,那大家都是怎么做的呢?但我知道的大多都是静态定时任务实现. 基于注解来创建定时任务非常简单,只需几行代码便可完成.实现如下: @Configuration @EnableScheduling public class SimpleScheduleTask { //10秒钟执行

  • Python测试线程应用程序过程解析

    这篇文章主要介绍了Python测试线程应用程序过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在本章中,我们将学习线程应用程序的测试.我们还将了解测试的重要性. 为什么要测试? 在我们深入讨论测试的重要性之前,我们需要知道测试的内容.一般来说,测试是一种了解某些东西是如何运作的技术.另一方面,特别是如果我们谈论计算机程序或软件,那么测试就是访问软件程序功能的技术. 在本节中,我们将讨论软件测试的重要性.在软件开发中,必须在向客户端发布软

  • python全局变量引用与修改过程解析

    这篇文章主要介绍了python全局变量引用与修改过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.引用 使用到的全局变量只是作为引用,不在函数中修改它的值的话,不需要加global关键字.如: #! /usr/bin/python a = 1 b = [2, 3] def func(): if a == 1: print("a: %d" %a) for i in range(4): if i in b: print(&quo

  • Java基于final修饰数据过程解析

    这篇文章主要介绍了Java基于final修饰数据过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 final是Java中的一个重要关键字,它可以修饰数据.方法和类,本篇将从final修饰的数据角度对final做出总结. final修饰的数据代表着:永远不变.意思是,一旦你用final修饰一块数据,你之后就只能看看它,你想修改它,没门. 我们不希望改变的数据有下面两种情况: 永不改变的编译时常量. //编译时知道其值 private fin

  • python打包成so文件过程解析

    这篇文章主要介绍了python打包成so文件过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 wget https://bootstrap.pypa.io/get-pip.py python get-pip.py pip install cython 编写setput.py文件: setup.py文件内容如下: from distutils.core import setup from distutils.extension import

  • python文字转语音实现过程解析

    这篇文章主要介绍了python文字转语音实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 使用百度接口 接口地址 https://ai.baidu.com/docs#/TTS-Online-Python-SDK/top 安装接口 pip install baidu-aip from aip import AipSpeech """ 你的 APPID AK SK """ APP_ID =

  • 基于springboot集成hbase过程解析

    这篇文章主要介绍了基于springboot集成hbase过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 springboot-habse: https://github.com/spring-projects/spring-hadoop-samples/tree/master/hbase 依赖: <dependency> <groupId>org.springframework.data</groupId> &

  • python使用rsa非对称加密过程解析

    这篇文章主要介绍了python使用rsa非对称加密过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.安装rsa 支持python 2.7 或者 python 3.5 以上版本 使用豆瓣pypi源来安装rsa pip install -i https://pypi.douban.com/simple rsa 2.加密解密 2.1.生成公私钥对 import rsa # 1.接收者(A)生成512位公私钥对 # a. lemon_pub为

  • Spring Cloud基于zuul实现网关过程解析

    这篇文章主要介绍了Spring Cloud基于zuul实现网关过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 利用zuul网关统一向外暴露接口 1.新建项目 spring-zuul 2.引入pom <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuu

随机推荐