使用 scrapy 爬虫框架,一般是边爬边去重还是爬完一定深度以后再去重?
目前刚学爬虫,已经实现爬虫入库,但是遇到一个瓶颈,因为是递归爬虫,所以会一直循环你爬取已经爬过的页面,毕竟很多首页都会有一个首页自己 self 的链接,所以,爬虫一直去请求他。
所以现在我想了解下,目前大家写的爬虫都是边去重边爬取的?还是入库以后再操作数据库去重?
如果是数据库去重的话,我感觉会导致数据库里一大堆无用的信息,太损耗效率了。
如果是边爬取边去重的话,我是从数据库里 select url 来匹配判断是否重复后再入库,还是另外建个列表,每次从内存里取(内存有限的情况下),哪个效率高?
或者说有更好的实现方法和理论?或者说 scrapy 本身有示例去重的接口或者函数?
感谢~感谢~
1
JhZ7z587cYROBgVQ 2016-06-07 18:58:45 +08:00
我的话之前使用 bloom filter 边爬边去重的,就是会有一定错误率。
|
2
zanpen2000 2016-06-07 18:59:49 +08:00
中间件去重,也就是边爬边去
|
3
billion 2016-06-07 19:39:27 +08:00
使用 Redis 储存网址,自带去重功能。
|
4
zts1993 2016-06-07 19:44:18 +08:00
Redis set 去重
|
5
silverfox 2016-06-07 20:36:48 +08:00
Scrapy 默认会去掉相同请求, http://doc.scrapy.org/en/latest/topics/settings.html#dupefilter-class
|
6
Allianzcortex 2016-06-08 08:34:08 +08:00
所以这就是自己为什么在写完 [scrapy-demos]( https://github.com/Allianzcortex/scrapy-demos) 后就决定再也不用 scrapy 的原因⊙﹏⊙b ……爬虫框架用起来自定义程度总是不高~
用 requests+Selenium+PhantomJs 多线程爬虫的时候用的是 mp.manager.dict() 来存储已经访问过的网站,如果发现再次访问就直接跳过 我能想到的就是 Bloom Filter ,按照上面所说用 redis 来去重应该也可以 |
7
phantomer OP |
8
brucedone 2016-06-08 14:01:31 +08:00 1
@Allianzcortex scrapy 的自由度还不高?基于插件形式你可以自由定制 proxy ,以及动态 js 解析(scrapy-splash),pipeline 可以自己定义输出形式,你觉得去重是一个难题,那自己定义 queue 的存储然后在重载 start_reqeust 方法就可以轻松的去重了,这些内容都可以自己做,其实已经耦合性不算太高了~
|
9
Allianzcortex 2016-06-08 17:28:57 +08:00 1
@brucedone 可能是我做的还没有到 GB 级这种数据,更喜欢自己写一些内部的东西吧。不过 scrapy 自定义 proxy 这种方式真是特别喜欢,因为我是 Django 党 O(∩_∩)O 哈哈哈~
|
10
BruceWang 2016-09-29 15:56:42 +08:00
|
12
BruceWang 2016-09-30 09:13:38 +08:00
@billion 我想,应该是“去重”这两个字定义不清的问题。
我觉得有这么几个地方需要去重: 1 、在单一页面解析的时候,可能会提取到重复的链接,需要 url 去重; 2 、在不同任务、不同页面解析的时候,可能会提取到重复的链接,需要 url 去重; 3 、在数据提取的时候,可能会遇到重复数据,比如一份重要性比较高的数据被多个不同的站点以各种形式引用(类似论文的引用,不过被引用的论文重复发表在多个期刊),需要 data 去重。 4 、其它还没想到的 我在做一个基于 Scrapy 的动态生成的爬虫,也就是提取规则等参数是从数据库取得的(我知道应该已经有了,不过我想自己造个轮子)。所以我对前文( 2 )的情况不是光用集合判断存在还是不存在,我还记录了上次访问时间和任务要求。如果按任务要求比如每周爬一次,判断时间满足那么就再爬一次,否则丢弃。 |