【Python】Python3网络爬虫实战-38、动态渲染页面抓取:Splash的使用

本文主要是介绍【Python】Python3网络爬虫实战-38、动态渲染页面抓取:Splash的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Splash 是一个 JavaScript 渲染服务,是一个带有 HTTP API 的轻量级浏览器,同时它对接了 Python 中的 Twisted和 QT 库,利用它我们同样可以实现动态渲染页面的抓取。

1. 功能介绍

利用 Splash 我们可以实现如下功能:

  • 异步方式处理多个网页渲染过程
  • 获取渲染后的页面的源代码或截图
  • 通过关闭图片渲染或者使用 Adblock 规则来加快页面渲染速度
  • 可执行特定的 JavaScript 脚本
  • 可通过 Lua 脚本来控制页面渲染过程获取渲染的详细过程并通过 HAR(HTTP Archive)格式呈现

接下来我们来了解一下它的具体用法。

2. 准备工作

在本节开始之前请确保已经正确安装好了 Splash 并可以正常运行服务,如没有安装可以参考第一章的安装说明。

3. 实例引入

首先我们可以通过 Splash 提供的 Web 页面来测试 Splash的渲染过程,例如我们在本机 8050 端口运行了 Splash 服务,打开:http://localhost:8050/ 即可看到其 Web 页面,如图 7-6 所示:

图 7-6 Web 页面
在右侧呈现的是一个渲染示例,我们可以看到在上方有一个输入框,默认是:http://google.com,我们在这里换成百度测试一下,将内容更改为:https://www.baidu.com,然后点击按钮,开始渲染,结果如图 7-7 所示:

图 7-7 运行结果
可以看到网页的返回结果呈现了渲染截图、HAR 加载统计数据、网页的源代码。
通过 HAR 的结果我们可以看到 Splash 执行了整个网页的渲染过程,包括 CSS、JavaScript 的加载等过程,呈现的页面和我们在浏览器得到的结果完全一致。
那么这个过程是由什么来控制的呢?我们重新返回首页可以看到实际上是有一段脚本,内容如下:

function main(splash, args)
  assert(splash:go(args.url))
  assert(splash:wait(0.5))
  return {
    html = splash:html(),
    png = splash:png(),
    har = splash:har(),
  }
end
Python资源分享qun 784758214 ,内有安装包,PDF,学习视频,这里是Python学习者的聚集地,零基础,进阶,都欢迎

这个脚本是实际是 Lua 语言写的脚本,Lua也是一门编程语言,简洁易用。
即使我们不懂这个语言的语法,但通过脚本表面意思我们也可以大致了解到它是首先调用 go() 方法去加载页面,然后调用 wait() 方法等待了一定的时间,最后返回了页面的源码、截图和 HAR 信息。
所以到这里我们可以大体了解到 Splash 是通过 Lua 脚本来控制了页面的加载过程,加载过程完全模拟浏览器,最后可返回各种格式的结果,如网页源码、截图等。
所以接下来我们要学会用 Splash 的话,一是需要了解其中 Lua 脚本的写法,二是需要了解相关 API 的用法,那么接下来我们就来了解一下这两部分内容。

4. Splash Lua脚本

Splash可以通过Lua脚本执行一系列渲染操作,这样我们就可以用Splash来模拟类似Chrome、PhantomJS的操作了。
首先我们先对 Splash Lua 脚本的用法有一个基本的认识,先了解一下它的入口和执行方式。

入口及返回值

首先我们来看一个基本实例:

function main(splash, args)splash:go("http://www.baidu.com")splash:wait(0.5)local title = splash:evaljs("document.title")return {title=title}
end

我们将代码粘贴到刚才我们所打开的:http://localhost:8050/ 的代码编辑区域,然后点击按钮来测试一下。
这样我们就会看到其返回了网页的标题,这里我们是通过 evaljs() 方法传入 JavaScript 脚本,而 document.title 的执行结果就是返回网页标题,执行完毕后赋值给一个 title 变量,随后将其返回,这样就可以看到其返回结果就是网页标题了,如图 7-8 所示:

图 7-8 运行结果
注意到我们在这里定义的方法名称叫做 main(),这个名称必须是固定的,Splash 会默认调用这个方法。
方法的返回值可以是字典形式、也可以是字符串形式,最后都会转化为一个 Splash HTTP Response,例如:

function main(splash)
    return {hello="world!"}
end

这样即返回了一个字典形式的内容。

function main(splash)
    return 'hello'
end

这样即返回了一个字符串形式的内容,同样是可以的。

异步处理

Splash是支持异步处理的,但是这里我们并没有显式地指明回调方法,其回调的跳转是在Splash内部完成的,我们先来看一个例子:

function main(splash, args)
  local example_urls = {"www.baidu.com", "www.taobao.com", "www.zhihu.com"}
  local urls = args.urls or example_urls
  local results = {}
  for index, url in ipairs(urls) do
    local ok, reason = splash:go("http://" .. url)
    if ok then
      splash:wait(2)
      results[url] = splash:png()
    end
  end
  return results
end

运行后的返回结果是三个站点的截图,如图 7-9 所示:

图 7-9 运行结果
在脚本内调用了 wait() 方法,这类似于 Python 中的 sleep(),参数为等待的秒数,当 Splash 执行到此方法时,它会转而去处理其他的任务,然后在指定的时间过后再回来继续处理。
在这里值得注意的是 Lua 脚本中的字符串拼接,和 Python不同,这里的字符串拼接使用的是 … 操作符,而不是 +,如有必要可以简单了解一下Lua脚本的语法,链接:http://www.runoob.com/lua/lua…。
另外这里我们做了加载时的异常检测,go() 方法会返回加载页面的结果状态,如果页面出现 4XX 或 5XX 状态码,ok 变量就会为空,就不会返回加载后的图片。

5. Splash对象属性

我们注意到在前面的例子中 main() 方法的第一个参数是 splash,这个对象非常重要,类似于在 Selenium 中的WebDriver 对象:

from selenium import webdriver
browser = webdriver.Chrome()

如上所示,现在的 splash 对象就如同此处 Selenium 中的 browser 对象,我们可以调用它的一些属性和方法来控制加载过程,接下来我们首先看下它的属性。

args

splash 对象的 args 属性可以获取加载时配置的参数,它可以获取加载的 URL,如果为 GET 请求它还可以获取 GET 请求参数,如果为 POST 请求它可以获取表单提交的数据。Splash 支持第二个参数直接作为 args,例如:

function main(splash, args)
    local url = args.url
end

在这里第二个参数 args 就相当于 splash.args 属性,以上代码等价于:

function main(splash)
    local url = splash.args.url
end

js_enabled

这个属性是 Splash 的 JavaScript 执行开关,我们可以将其配置为 True 或 False 来控制是否可以执行 JavaScript 代码,默认为 True,例如我们在这里禁用一下 JavaScript 的执行:

function main(splash, args)
  splash:go("https://www.baidu.com")
  splash.js_enabled = false
  local title = splash:evaljs("document.title")
  return {title=title}
end

禁用之后,我们重新调用了 evaljs() 方法执行 JavaScript 代码,那么运行结果就会抛出异常:

{
    "error": 400,
    "type": "ScriptError",
    "info": {
        "type": "JS_ERROR",
        "js_error_message": null,
        "source": "[string \"function main(splash, args)\r...\"]",
        "message": "[string \"function main(splash, args)\r...\"]:4: unknown JS error: None",
        "line_number": 4,
        "error": "unknown JS error: None",
        "splash_method": "evaljs"
    },
    "description": "Error happened while executing Lua script"
}

不过一般来说我们不用设置此属性开关,默认开启即可。

resource_timeout

此属性可以设置加载的超时时间,单位是秒,如果设置为 0或 nil(类似 Python 中的 None)就代表不检测超时,我们用一个实例感受一下:

function main(splash)
    splash.resource_timeout = 0.1
    assert(splash:go('https://www.taobao.com'))
    return splash:png()
end

例如这里我们将超时时间设置为 0.1 秒,如果在 0.1 秒之内没有得到响应就会抛出异常,错误如下:

{
    "error": 400,
    "type": "ScriptError",
    "info": {
        "error": "network5",
        "type": "LUA_ERROR",
        "line_number": 3,
        "source": "[string \"function main(splash)\r...\"]",
        "message": "Lua error: [string \"function main(splash)\r...\"]:3: network5"
    },
    "description": "Error happened while executing Lua script"
}

此属性适合在网页加载速度较慢的情况下设置,如果超过了某个时间无响应则直接抛出异常并忽略即可。

images_enabled

此属性可以设置图片是否加载,默认情况下是加载的,但是禁用之后可以节省网络流量并提高网页加载速度,但是值得注意的是禁用图片加载之后可能会影响 JavaScript 渲染,因为禁用图片之后它的外层 DOM 节点的高度会受影响,进而影响 DOM 节点的位置,所以如果 JavaScript 如果使用了相关变量的话,其执行就会受到影响,不过一般情况下不会。
另外值得注意的是 Splash 使用了缓存,所以如果你一开始加载出来了网页图片,然后禁用了图片加载,然后再重新加载页面,之前加载好的图片可能还会显示出来,这时可以重启一下 Splash 即可解决。
禁用图片加载的示例如下:

function main(splash, args)
  splash.images_enabled = false
  assert(splash:go('https://www.jd.com'))
  return {png=splash:png()}
end

这样返回的页面截图就不会带有任何图片,加载速度也会快很多。

plugins

这篇关于【Python】Python3网络爬虫实战-38、动态渲染页面抓取:Splash的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/276762

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表