Python 爬虫修养-处理动态网页

本文转自:i春秋社区

0x01 前言
在进行爬虫开发的过程中,我们会遇到很多的棘手的问题,当然对于普通的问题比如 UA 等修改的问题,我们并不在讨论范围,既然要将修养,自然不能说这些完全没有意思的小问题。
0x02 Selenium + PhantomJS
这个东西算是老生长谈的问题吧,基本我在问身边的朋友们的时候,他们都能讲出这条解决方案:

Selenium + PhantomJS(Firefox Chrome之类的)

但是真正的有实践过的人,是不会把这个东西投入生产环境的,首先最大的问题就是Selenium + PhantomJS 非常的慢,这种慢的原因就是因为他要加载这个网页所有的内容,比如图片资源,link 中的 CSS,JS 都会加载,而且还会渲染整个网页,在渲染结束之后才会允许你操作网页的元素。当然可能会有读者问,Selenium 作为可以自动化编写测试脚本的一个模块,他是自带 HOOK 功能的,在 Selenium 的 API 中也有介绍说 Selenium 可以控制等待某一个元素加载成功时返回页面数据。
没错的确是这样的,我们确实可以使用 Selenium 的内置 api 去操作浏览器完成各种各样的操作,比如模拟点击,模拟填表,甚至执行 js,但是最大的问题我们还是没有解决:归根结底是操作浏览器来进行工作的,启动需要打开浏览器(等待一定时间),访问网页之后渲染,下载相应资源,执行 JS,这么多的步骤,每一个步骤都需要或多或少的等待时间,这就好比,我们就是在使用浏览器做这样的事情,只不过是加上了精准的鼠标定位而已。

当然说了这么多,Selenium 虽然不适合做生产解决方案,也并不是没有别的解决办法了。
0x03 execjs
execjs 是一个在 Python 中执行 js 的模块,听到这个,大家可能会觉得耳目一新:欸?那我是不是可以爬虫爬下来 js 代码然后手动控制 js 执行,然后就可以控制自己想要的元素,拿到想要的结果,而且也并不丢失效率。
但是我要说这样的想法,实际上是非常的 naive,虽然有了这个 js 引擎,但是,我们需要很多很多的轮子,为什么呢?来听我一步一步解释:
1. js 的强大之处其实并不在于松散的语法与容错,而是在于对 BOM 对象和 DOM 对象的操作。举个例子来说,比如,一个网页的表单,是通过操作执行 js 来提交的。 那么,问题就在于你有办法仅仅用这个 execjs 来执行这段 js 来提交表单么? 显然,这是行不通的。为什么呢?因为对于我们来说的话 execjs 是一个独立的模块,我们没有办法把我们静态扒下来的html 文档和 execjs 建立联系。
2. 如果非要建立联系,那么你需要自己完成 js 对 html 的 DOM 对象的绑定,具体怎么完成呢?js 在浏览器中怎么与 DOM 树绑定,你就需要怎么去做。但是要怎么做啊,首先你需要一个自己构建 DOM 树,然后才能进行手动绑定。这个轮子,确实是非常的大。
 
但是如果你真的有大把的时间,那么应该怎么去做这个事情呢?没错要不你去 HOOK 一个webkit 要不你去自己构建一个 html 的解析器。那么我就在这里稍微提一下这个很有趣的事情:如果构建一个 HTML 解析器:
最近有用 PLY 写过一个 Lexer 当时准备做个解析 DOM 树的 HTML 解析器,自己实践第一步也是觉得这个东西理论上是完全可行的,但是能不能完成就要看个人毅力和你个人的编程能力了。
0x04 Ghost
关于 Ghost 的话,其实我个人是比较推崇的,但是其实他也并不是特别完美,它对我来说,更像是一个 Selenium 与PhantomJS 的结合体,怎么说呢,实际上 ghost 这个模块用的是QT 中的 webkit,在安装的时候就得被迫安装 pyside 或者 pyqt4,实际上我当时还是很难理解为什么一个这个东西没有图形界面要使用 qt 和 pyside 这种东西作为引擎呢?单独构造一个浏览器引擎真的就这么困难么?其实装好了也没什么关系,毕竟我觉得还是要比Selenium 配 PhantomJS 好用的。
话说回来,我们就来讨论一下这个 Ghost 的一些问题。
首先,使用 Ghost 的一个好处是我们并不需要再将一个 binary 的浏览器放在路径下了,以至于我们不需要去花费时间打开浏览器了,因为 ghost 就是一个功能完全的 Python 实现(借助 qt 的 webkit)的轻量级没有图形化的浏览器。
而且,ghost 在初始化的时候,有一个选项可以不下载图片,但是没有办法阻止它下载 js 和css, 其实这个也是可以原谅的,毕竟自己在使用的时候,也是需要自己去下载 js 在本地筛选。
于此同时 ghost 还是提供了相应的 API 这些 API 和 selenium 的 API 功能基本差别不是特别大,也会有处理表单,执行 ajax 去加载动态页面,这样来说 ghost 是一个完美的解决方案么?
其实还是有他自己的缺点的,就是我们还是不能完全控制每一个过程,比如我们如果只想让它解析 DOM 树,不动态执行 js 脚本,而且,我想获取他的 DOM 树手动进行一些操作。这些都是没有办法的。但是也并不是完全没有办法,比如国内某厂他们就做了 HOOK 了一个浏览器去检测 XSS 这个思路我们可以在以后的文章中提出,具体的操作的话,这就要看大家的编程功底了。

0x05 原理总结
当然,懂得归纳的读者其实早就已经看出来了,对动态网页(通过 js 加载)的网页的信息采集,主要分成三种方案:
1. 基于实体浏览器操作解决方案(适用于测试环境不适用于大量信息采集)。
2. 基于深度控制 JS 脚本执行的解决方案(速度最快,编写难度最大)。
3. 基于 webkit 的解决方案。(相对较为折衷)
 

Python 爬虫修养-处理动态网页的更多相关文章

  1. Python爬虫之路——简单网页抓图升级版(添加多线程支持)

    转载自我的博客:http://www.mylonly.com/archives/1418.html 经过两个晚上的奋斗.将上一篇文章介绍的爬虫略微改进了下(Python爬虫之路--简单网页抓图),主要 ...

  2. python网络爬虫抓取动态网页并将数据存入数据库MySQL

    简述以下的代码是使用python实现的网络爬虫,抓取动态网页 http://hb.qq.com/baoliao/ .此网页中的最新.精华下面的内容是由JavaScript动态生成的.审查网页元素与网页 ...

  3. [Python爬虫] Selenium+Phantomjs动态获取CSDN下载资源信息和评论

    前面几篇文章介绍了Selenium.PhantomJS的基础知识及安装过程,这篇文章是一篇应用.通过Selenium调用Phantomjs获取CSDN下载资源的信息,最重要的是动态获取资源的评论,它是 ...

  4. 在python使用selenium获取动态网页信息并用BeautifulSoup进行解析--动态网页爬虫

    爬虫抓取数据时有些数据是动态数据,例如是用js动态加载的,使用普通的urllib2 抓取数据是找不到相关数据的,这是爬虫初学者在使用的过程中,最容易发生的情况,明明在浏览器里有相应的信息,但是在pyt ...

  5. Python爬虫学习之获取网页源码

    偶然的机会,在知乎上看到一个有关爬虫的话题<利用爬虫技术能做到哪些很酷很有趣很有用的事情?>,因为强烈的好奇心和觉得会写爬虫是一件高大上的事情,所以就对爬虫产生了兴趣. 关于网络爬虫的定义 ...

  6. Python爬虫实战:将网页转换为pdf电子书

    写爬虫似乎没有比用 Python 更合适了,Python 社区提供的爬虫工具多得让你眼花缭乱,各种拿来就可以直接用的 library 分分钟就可以写出一个爬虫出来,今天就琢磨着写一个爬虫,将廖雪峰的 ...

  7. python 爬虫(爬取网页的img并下载)

    from urllib.request import urlopen # 引用第三方库 import requests #引用requests/用于访问网站(没安装需要安装) from pyquery ...

  8. 2019-03-14 Python爬虫问题 爬取网页的汉字打印出来乱码

    html = requests.get(YieldCurveUrl, headers=headers) html=html.content.decode('UTF-8') # print(html) ...

  9. [python爬虫] Selenium常见元素定位方法和操作的学习介绍

    这篇文章主要Selenium+Python自动测试或爬虫中的常见定位方法.鼠标操作.键盘操作介绍,希望该篇基础性文章对你有所帮助,如果有错误或不足之处,请海涵~同时CSDN总是屏蔽这篇文章,再加上最近 ...

随机推荐

  1. CRM--自定义stark

    一:启动 解释django的启动 完成以上两步,在app01下创建stark.py文件,就会被加载 (admin.py就是这样启动的) 二:注册 三:设计urls 四:增删改查

  2. python day03_ 文件处理

    一.文件操作的基本流程 计算机操作文件的过程 #1. 打开文件,得到文件句柄并赋值给一个变量 #2. 通过句柄对文件进行操作 #3. 关闭文件 1.文件的打开过程 # f被程序持有,文件被操作系统持有 ...

  3. Java几种常用JSON库性能比较

    本篇通过JMH来测试一下Java中几种常见的JSON解析库的性能. 每次都在网上看到别人说什么某某库性能是如何如何的好,碾压其他的库.但是百闻不如一见,只有自己亲手测试过的才是最值得相信的. JSON ...

  4. Android设备直接运行java项目?还杀不死?

    思路:拿到dex可执行文件,使用android执行 使用idea创建java类库,写相关逻辑代码 使用idea导出该类库jar包 使用android dx工具 将jar文件转换为dex可执行文件 dx ...

  5. session cookie简介

    会话机制:Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身 ...

  6. Ubuntu学习之路

    一. Ubuntu简介 Ubuntu(乌班图)是一个基于Debian的以桌面应用为主的Linux操作系统,据说其名称来自非洲南部祖鲁语或科萨语的“ubuntu”一词,意思是“人性”.“我的存在是因为大 ...

  7. 【机器学习】主成分分析法 PCA (II)

    主成分分析法(PAC)的优化——选择主成分的数量 根据上一讲,我们知道协方差为① 而训练集的方差为②. 我们希望在方差尽可能小的情况下选择尽可能小的K值. 也就是说我们需要找到k值使得①/②的值尽可能 ...

  8. 【此处有干货~】jmeter+ant+jenkins持续集成配置及过程中问题解决思路

    本人是一枚工作近三年的小测试,大学正好专业为软件测试,在工作中用到最多的是功能测试.接口测试.压力测试.偶尔会涉及到性能测试......(小白,很多观念技术跟大佬差距太大,勿喷) 在接口测试过程当中, ...

  9. pytest框架之fixture详细使用

    本人之前写了一套基于unnitest框架的UI自动化框架,但是发现了pytest框架之后觉得unnitest太low,现在重头开始学pytest框架,一边学习一边记录,和大家分享,话不多说,那就先从p ...

  10. tensorflow学习之(九)classification 分类问题之分类手写数字0-9

    #classification 分类问题 #例子 分类手写数字0-9 import tensorflow as tf from tensorflow.examples.tutorials.mnist ...