爬虫的增量式抓取和数据更新

不管是产生新页面,还是原本的页面更新,这种变化都被称为增量, 而爬取过程则被称为增量爬取。那如何进行增量式的爬取工作呢?回想一下爬虫的工作流程:

发送URL请求 ----- 获得响应 ----- 解析内容 ----- 存储内容

我们可以从几种思路入手:

  • 在发送请求之前判断这个URL是不是之前爬取过
  • 在解析内容后判断这部分内容是不是之前爬取过
  • 写入存储介质时判断内容是不是已经在介质中存在

 

实现增量式爬取

不难发现,其实增量爬取的核心是去重, 至于去重的操作在哪个步骤起作用,只能说各有利弊,就像我说的,everything is tradeoff。

在我看来,前两种思路需要根据实际情况取一个(也可能都用)。第一种思路适合不断有新页面出现的网站,比如说小说的新章节,每天的最新新闻等等;第二种思路则适合页面内容会更新的网站。第三个思路是相当于是最后的一道防线。这样做可以最大程度上达到去重的目的。

去重的方法

最简单的去重方式自然是将所有访问过的URL和其对应的内容保存下来,然后过一段时间重新爬取一次并进行比较,然后决定是否需要覆盖。这显然是不实际的,因为会消耗很多资源。目前比较实际的做法就是给URL或者其内容(取决于这个网站采用哪种更新方式)上一个标识,这个标识有个比较好听的名字,叫数据指纹

这里很容易想到的一种数据指纹就是哈希值,根据哈希函数的特性,我们可以为任意内容生成一个独一无二的定长字符串,之后只要比较这个哈希值就行了。哈希值是一个很伟大的发明,几乎在任何地方都有它的影子,它利用数学特性,计算机只要经过简单的计算就可以得到唯一的特征值,这个计算过程的开销基本可以忽略不计,当然这是题外话了。

不过即使用了哈希值,你仍需要一个地方存储所有的哈希值,并且要能做到方便的取用。如果你的存储介质是数据库,一般的数据库系统都能提供索引,如果把哈希值作为唯一索引呢,这应该是可行的。有些数据库也提供查询后再插入的操作,不过本质上应该也是索引。和哈希值类似的还有MD5校验码,殊途同归。

除了自建指纹,其实在发送请求时还有一些技巧,比如说304状态码,Last-modified字段,文件大小和MD5签名。具体参考[8],很好理解,就不细说了。

综上所述,在数据量不大的时候,几百个或者就几千个的时候,简单自己写个小函数或者利用集合的特性去重就行了。如果数据量够大,数据指纹的价值就体现出来了,它可以节省可观的空间,同时可以引入BloomFilter作为去重的手段。另外,如果要对数据做持久化(简单说就是去重操作不会被事故影响,比如说断电),就需要用到Redis数据库

Redis

Python的Redis客户端库也是开源的,地址是:redis-py。不过在开始之前,你首先需要一个有Redis数据库运行的主机(搭建一个很简单)。

关于Redis数据库还有几个关键词:key-value,高性能,数据持久化,数据备份,原子操作以及跟这里相关的一个特性:支持集合数据类型。这才是为什么做增量爬取时我们要用到Redis数据库:我们可以通过将URL或者页面内容的指纹作为key存入Redis数据库中的集合里,利用集合的不重复性达到去重的目的,每次爬虫要处理URL或者页面时会先去Redis数据库里检查一下是否已经存在,因为Redis数据库着力于key-value形式的存储,所以这一步的速度将会很可观;其次Redis可以将内存中的内容持久化到磁盘,并且其每一次操作都是原子操作,这就保证了爬虫的可靠性,即爬虫不会应为意外停止而损失数据。

但应该如何将这一特性融入到爬虫中呢?如果是自己写的爬虫代码,添加上述代码即可;如果使用的是scrapy框架,我们可以在middleware上下功夫,在spider模块收到要处理的URL时,写一个Spider中间件用来判断这条URL的指纹是否在Redis数据库中存在,如果存在的话,就直接舍弃这条URL;如果是要判断页面的内容是否更新,可以在Download中间件中添加代码来校验,原理一样。当然,数据库的操作可以用类似write()和query()的方法进行封装,此处不表。

参考:


(1).https://www.cnblogs.com/zbllly/p/10283943.html

(2).https://blog.csdn.net/yubei2155/article/details/79343893   = Python爬虫定时增量更新数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/273870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Data JPA初使用 *****重要********

Spring Data JPA初使用我们都知道Spring是一个非常优秀的JavaEE整合框架,它尽可能的减少我们开发的工作量和难度。在持久层的业务逻辑方面,Spring开源组织又给我们带来了同样优秀的Spring Data JPA。通常我们写持久层,都是先写一个接口&#…

flask-笔记

-super() 使用super()保留基模板中定义的原始内容 - link标签: 用来指定当前文档和外部资源的关系。它最常见的是用来链接样式表,也用来创建网站图标(既是网站图标样式也包括移动设备和app图标)。 -csrf: CSRF概念:CSRF跨站点请求伪造(…

MySQL 无法连接

Host localhost is not allowed to connect to this MySQL server 错误 解决办法: C:\Program Files\MySQL\MySQL Server 5.5\my.ini 在[mysqld]下加下面两行, skip-name-resolve skip-grant-tables 重启mysql的windows服务,在mysql命令行界面…

能让你少写1000行代码的20个正则表达式

参考: (1).http://www.codeceo.com/article/20-regular-expressions.html

http请求中的Query String Parameters、Form Data、Request Payload

参考: (1).(http请求参数之Query String Parameters、Form Data、Request Payload) - https://www.jianshu.com/p/c81ec1a547ad

蜜罐

http://www.projecthoneypot.org/home.php转载于:https://www.cnblogs.com/diyunpeng/p/3534507.html

php中json_decode返回数组或对象的实例

1.json_decode() json_decode (PHP 5 > 5.2.0, PECL json > 1.2.0) json_decode — 对 JSON 格式的字符串进行编码 说明 mixed json_decode ( string $json [, bool $assoc ] ) 接受一个 JSON 格式的字符串并且把它转换为 PHP 变量 参数 json 待解码的 json string 格式的…

如何精通js

参考: (1.)https://www.zhihu.com/search?typecontent&q%E5%A6%82%E4%BD%95%E7%B2%BE%E9%80%9Ajs

程序员怎么样才能进入微软?

程序员怎么样才能进入微软? 程序员到微软中国总裁 “打工皇帝”长沙晒成功之道 程序员面试之道之走进微软 应该是西北大学的学生,距离我好近(我也在西安),可是又好远(人家拿到了MS的offer)。 专…

python中的装饰器-(重复阅读)

---1--- 假设我们要增强某个函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改某个函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 装饰器本质上是一个Python…

[转帖]好技术领导,差技术领导

团队合作一个优秀的技术领导必然是团队的一份子,他们认为当整个团队成功时自己才称得上成功。他们不仅要做好繁杂和不讨好的本职工作,还要清除项目中的障碍,从而让整个团队能够以100%的效率运转起来。一个好的技术领导会努力拓宽团队在技术上…

python有哪些常用的库

参考: (1).https://www.zhihu.com/question/20501628/answer/19542741(Python 常用的标准库以及第三方库有哪些?)

C#打开文件对话框和文件夹对话框

打开文件对话框OpenFileDialog OpenFileDialog ofd new OpenFileDialog();ofd.Filter "Excel文件(*.xls;*.xlsx)|*.xls;*.xlsx|所有文件|*.*";ofd.ValidateNames true;ofd.CheckPathExists true;ofd.CheckFileExists true;if (ofd.ShowDialog() DialogResult.O…

debian安装flash插件

$ sudo apt-get install flashplugin-nonfree 转载于:https://www.cnblogs.com/vipzrx/p/3554839.html

python中的拷贝

1.赋值: 只是复制了新对象的引用,不会开辟新的内存空间。 2.浅拷贝: 创建新对象,其内容是原对象的引用。 浅拷贝有三种形式:切片操作,工厂函数,copy模块中的copy函数。 如: lst [1,2,3,[4,5]] …

ZOJ 2112 Dynamic Rankings

这里是题目地址 其实就是带修改的区间第K大。 写了一下BIT套主席树,内存飞起,似乎需要特别的优化技巧 所以还是写了一下线段树套平衡树,跑了1s左右。 其实线段树套平衡树就是归并树的自然扩展而已。 归并树是把归并排序的过程建成一颗线段树…

python3[进阶]8.对象引用、可变性和垃圾回收

文章目录8.1变量不是盒子8.2 标识,相等性和别名8.2.1 在和is之间选择8.2.2 元组的相对不可变性8.3 默认做浅复制(拓展)为任意对象做深复制和浅复制深拷贝和浅拷贝有什么具体的区别呢?8.4 函数的参数作为引用时8.4.1 不要使用可变类型作为参数…

openfire修改服务器名称方法

1.登陆openfire管理页面,在主页面下方选择编辑属性,修改服务器名称为当前主机名称,点击保存属性,按页面提示重启服务器。 2.重启后,主页的服务器属性下的服务器名称出现一个叹号,鼠标放上去显示Found RSA c…

python (第八章)补充-可迭代对象(补充高阶函数,以及常用的高阶函数)

文章目录可迭代对象迭代器什么是迭代器什么是生成器生成器的作用生成器的注意事项总结:高阶函数什么是高阶函数?map()函数filter()函数reduce()函数参考可迭代对象 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类…

网络阅读开篇

网络阅读也符合马太效应,投入的时间越多,获取的有效信息却越来越少,因此做出以下规定: 1、限制网络阅读时间; 2、每次阅读做总结。 本来想的挺简单的,随便搜了一下,居然一部小心拜读了两位大神的…