htmlunit抓取动态网页(Python开发的一个快速,高层次高层次架构架构)

优采云 发布时间: 2022-02-27 11:00

  htmlunit抓取动态网页(Python开发的一个快速,高层次高层次架构架构)

  8.参考文章

  0x01 爬虫架构

  说到爬虫架构,不得不提Scrapy的爬虫架构。Scrapy 是一个用 Python 开发的快速、高级的爬虫框架,用于爬取网站并从页面中提取结构化数据。Scrapy 用途广泛,可用于数据挖掘、监控和自动化测试。Scrapy 的吸引力在于它是一个任何人都可以根据自己的需要轻松修改的框架。它还为各种类型的爬虫提供了基类,例如BaseSpider、站点地图爬虫等。

  

  上图是Scrapy的架构图。绿线是数据流。从初始 URL 开始,Scheduler 会将其交给 Downloader 进行下载。下载完成后交给 Spider 进行分析,将要保存的数据发送到 Item Pipeline ,也就是对数据进行后处理。此外,可以在数据流通道中安装各种中间件,进行必要的处理。因此,在开发爬虫时,最好先规划好各个模块。我的做法是分别规划下载模块、爬取模块、调度模块、数据存储模块。

  0x02 页面下载和解析页面下载

  页面下载分为静态下载和动态下载两种方式。

  传统爬虫采用静态下载方式。静态下载的好处是下载过程很快,但是页面只是一个乏味的html。所以在页面链接分析中只获取标签的href属性,或者高手自行分析js、form等标签。捕获一些链接。在python中,可以使用urllib2模块或者requests模块来实现功能。动态爬虫在 web2.0 时代具有特殊的优势。由于网页是通过javascript处理的,所以网页的内容是通过Ajax异步获取的。因此,动态爬虫需要对页面经过javascript处理和ajax进行分析才能获取内容。目前简单的解决方法是直接通过基于 webkit 的模块来处理它。PYQT4、的三个模块 Splinter 和 Selenium 都可以达到目的。对于爬虫来说,不需要浏览器界面,所以使用无头浏览器是非常划算的。HtmlUnit 和 phantomjs 都是可以使用的无头浏览器。

  

  以上代码是访问新浪网的主站。通过比较静态爬虫页面和动态爬虫页面的长度,比较静态爬虫页面和动态爬虫页面爬取的链接数。

  

  静态爬取时,页面长度为563838,页面内爬取的链接数只有166个。动态爬取时,页面长度增加到695991,链接数达到1422,接近10-倍增。

  抓取链接表达式

  常规:pile(“href=\”([^\”]*)\””)

  Xpath: xpath('//*[@href]')

  页面解析

  页面解析是一个模块,它捕获页面内的链接并爬取特定数据。页面解析主要处理的是字符串,而html是一个特殊的字符串。在Python中,re、beautifulsoup、HTMLParser、lxml等模块都可以解决问题。对于链接,主要是抓取a标签下的href属性,以及其他一些标签的src属性。

  0x03 URL去重

  URL去重是爬虫操作的关键步骤。由于正在运行的爬虫主要被阻塞在网络交互中,因此避免重复的网络交互非常重要。爬虫一般将要爬取的 URL 放入队列中,从爬取的网页中提取新的 URL。在将它们放入队列之前,它们必须首先确保这些新 URL 未被抓取。如果之前已经爬过,不再放入队列中。

  哈希表

  使用哈希表进行去重一般是最容易想到的方法,因为哈希表查询的时间复杂度是O(1),而当哈希表足够大的时候,哈希冲突的概率就变得非常高了所以判断URL是否重复的准确率是很高的,使用哈希表去重是比较简单的解决方案,但是普通的哈希表也有明显的缺陷,考虑到内存,使用大的哈希表是不合适。字典数据结构可以在Python中使用。

  网址压缩

  如果在哈希表中,当每个节点以str的形式存储一个特定的URL时,是非常占用内存的。如果将 URL 压缩成 int 类型的变量,内存使用量将减少 3 倍以上。因此,您可以使用 Python 的 hashlib 模块进行 URL 压缩。思路:将哈希表的节点数据结构设置为集合,将压缩后的URL存放在集合中。

  布隆过滤器

  Bloom Filter 可以节省大量存储空间,而且错误很少。Bloom Filter 是一组定义在 n 个输入键上的 k 个哈希函数,将上述 n 个键映射到 m 位上的数据容器。

  

  上图清楚地说明了布隆过滤器的优势。在可控容器长度内,当所有哈希函数对同一元素计算的哈希值为1时,判断该元素存在。Python中的hashlib自带了多种hash函数,包括MD5、sha1、sha224、sha256、sha384、sha512。代码也可以加盐,非常方便。Bloom Filter 也会造成冲突,详见文章末尾的参考文章。

  在Python编程过程中,可以使用jaybaird提供的BloomFilter接口,也可以自己搭建轮子。

  细节

  有个小细节,在构建哈希表的时候选择容器很重要。哈希表占用太多空间是一个非常令人不快的问题。因此,以下方法可以解决爬虫去重的一些问题。

  

  上面的代码只是简单地验证了生成容器的运行时间。

  

  从上图可以看出,在构建一个长度为1亿的容器时,选择列表容器程序耗时7.2s,选择一个字符串作为运行时间的容器。

  接下来,查看内存使用情况。

  

  如果构建一个1亿的列表占用794660k的内存。

  

  但是创建一个1亿长度的字符串会占用109,720k的内存,空间占用减少了大约700,000k。

  0x04 网址相似度

  主要算法

  对于URL相似度,我只是实践了一个很简单的方法。

  在保证不重复爬取的情况下,还需要对相似的URL进行判断。我使用海绵和ly5066113提供的想法。具体信息参考文章。

  下面是一组可以判断为相似的URL组

  正如预期的那样,上面的 URL 应该合并到

  思路如下,需要提取以下特征

  1、主机串

  2.目录深度(用'/'隔开)

  3. 最后一页功能

  具体算法

  

  算法本身很好,一看就懂。

  实际效果:

  

  上图显示了8个不同的url,计算了2个值。通过实践,在上千万的哈希表中,冲突情况是可以接受的。

  0x05 并发操作

  Python中并发操作涉及的主要模型有:多线程模型、多进程模型、协程模型。Elias 专门写了一篇文章文章,对比了几种常用模型并发方案的性能。对于爬虫本身来说,限制爬虫的速度主要来自于目标服务器的响应速度,所以选择一个容易控制的模块是对的。

  多线程模型

  多线程模型是最容易上手的。Python自带的threading模块可以很好的实现并发需求,配合Queue模块实现数据共享。

  多进程模型

  多处理模型类似于多线程模型,多处理模块中有类似的Queue模块来实现数据共享。在linux中,用户态进程可以利用多核,所以在多核的上下文中,可以解决爬虫并发的问题。

  协程模型

  协程模型,在 Elias 的 文章 中,基于 greenlet 的协程程序的性能仅次于 Stackless Python,速度大约是 Stackless Python 的两倍,比其他解决方案快近一个数量级。因此,基于gevent(封装greenlets)的并发程序将具有良好的性能优势。

  具体描述gevent(非阻塞异步IO)。, “Gevent是一个基于协程的Python网络库,使用Greenlet提供的高级同步API,封装了libevent事件循环。”

  从实际编程效果来看,协程模型确实表现得非常好,运行结果的可控性明显更强,gevent库的封装非常好用。

  0x06 数据存储

  有许多技术是为数据存储本身而设计的。作为配菜不敢多说,但还是有一些工作中的小经验可以分享。

  前提:使用关系型数据库,测试中选择mysql,其他和sqlite差不多,和SqlServer的思路没有区别。

  我们做数据存储的时候,目的是减少与数据库的交互,这样可以提高性能。通常,每读取一个 URL 节点,就进行一次数据存储,这样的逻辑就会进行一次无限循环。其实这样的性能体验很差,存储速度也很慢。

  对于高级方法,为了减少与数据库的交互次数,每次与数据库的交互从发送1个节点变为发送10个节点到发送100个节点内容,因此效率提高了10到100倍。在实际应用中,效果非常好。:D

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线