爬虫抽取连接和抽取内容的部分是不是应该分开?

2014-02-26 11:50:02 +08:00
 yakczh
一般抽取链接的逻辑都比较简单,有些定向爬取的的可以象 chilcat用正则匹配AddAvoidOutboundLinkPattern("xxx") 那样设置成参数 ,但是内容抽取跟实际需求相关,而且网站改版以后这部分怎么需要重写,而且一个种子站点,可能抽取的数据是多个部分,相当于一个链接抽取的处理器,和一个内容抽取的处理器,内容处理器可能是1-n个,这样设计的话比较清晰,但是一个抓取一html内容,相对于一个函数里同时获取链接和内容,这样每次分开处理应该会对性能有一定影响
4663 次点击
所在节点    Python
11 条回复
lecher
2014-02-26 12:20:05 +08:00
取决于规模,当你的规模上去之后,分开是必然的,为了保证不受网络请求延时的影响,消息通信的时候可能还要上请求队列。
规模不大,请求不高的时候,怎么方便怎么来。只要模块接口条理清晰python重构还挺快的。
diaoleona
2014-02-26 12:22:16 +08:00
看你怎么设计了,我之前是爬到的response.url和 web content压缩一下放在一个数据库里,然后根据需求再做不同的抽取
pubby
2014-02-26 21:18:44 +08:00
我们用的比较多的架构是这样的:
Job Server: gearman
fetch_worker: 用node.js写的一个抓取脚本,连上gearman获取并处理抓取任务,支持socks5代理,worker数量动态自动调整,可分布到多台机器
队列服务: RabbitMQ
KV存储: 我们用redis-storage,一个redis接口+leveldb存储后端的东西,本身支持snappy压缩


处理流程是这样的:
1. 一个抓取调度进程
1.1 从rabbitmq读取抓取url
1.2 预处理后交给gearman,预处理包括抓取频率的控制,代理服务器的决策等
1.3 抓取结果存储,写入redis-storage服务器
1.4 写入rabbitmq队列通知分析进程处理
1.5 对于需要跳转或者需要重试的抓取,把url再次插入rabbitmq抓取队列即可。
1.6 遇到404等错误,直接丢弃结果

2. 一个数据分析进程
1.1 从rabbitmq队列获抓取成功的消息
1.2 从redis-storage服务器提取页面数据
1.3 如果是过渡页,分析下一步的url插入抓取队列
1.4 如果是目标页,分析信息,保存结果


我们主要用php
pubby
2014-02-26 21:45:09 +08:00
看具体需求而定的。
抓取规模,抓取周期,处理流程


如果是一次性的,怎么简单怎么来,想这么多.....
yakczh
2014-02-26 21:45:51 +08:00
你说的这种是链接专门在一个页面,数据在另一个页面, 假如一个页面同时有数据和链接呢?

另外数据页面可能有多个区域
yakczh
2014-02-26 21:58:14 +08:00
@pubby 简单的都很好说,就不说了
我在看scrapy, 貌似一个种子站点,一个详情页面一个数据块这种的很好处理,但是比较种子站点多个页面,多个页面都可能有数据,每个页面有多个数据区域的话,还不知道怎么写,http://stackoverflow.com/questions/21323123/scrapy-storing-items-across-multiple-formrequest-pages-meta-python 其他人也有类似的问题

我觉得合理的配置是按urlpatten来配置, 一个patten对应一个页面,和一个parse函数,如果数据在详情页,就写一个parse函数,如果多个页面,分别写多个parser,每个parse中处理的xpath都不同
另外多个parse函数中的items可以平行地收集,(相当于parse是支流,items汇总) 也可以在items里加个一个urlpatten的key,这样各收集各的,两种都支持更灵活一些
pubby
2014-02-26 23:47:55 +08:00
@yakczh

这个..... 上面只是一个基本框架

实际上确实碰到你说的情况,所以数据分析也分步骤的,并且队列也有多个分别对应每个步骤
或者在单个队列里面对的数据进行标记,表示它是那个站,哪个步骤的待处理信息

比如第一步,得到某个列表页,得到的url进入第二步的待抓取队列
第二步分析目标页,如果内容全了就ok,不全就增加步骤

所有步骤走完了才得到完整信息,中间某个步骤失败了,数据就是不完整的。


但是不管多少步骤,抽象出来每一步就是简单的 抓取->分析

“抓取”比较简单,就是准备任务扔给gearman,除非某些抓取需要带上特殊条件而需要一个特别点的实现
“分析”就是要针对不同站,实现每一个步骤的分析过程了

增加新的抓取目标站,就是做3件事情:
1. 定义新的站点,和步骤标记
2. 实现新的“抓取”,如果没有特殊性,可以用通用的
3. 实现新的“分析”

至于parser的实现,那就五花八门了,正则、DOM、json、甚至node.js解jsonp回掉数据,取决于目标站变态程度

目前我们实际用的就是这么个架构和流程,
rabbitmq中差不多有7G的消息队列,没办法抓取速度永远赶不上分析速度。
有时候内存吃紧,只能“忍痛”从队列中砍掉一大片

另外一点就是:如果存在多个步骤,那么后面步骤的抓取url要放入优先级高的队列,优先处理,要不然排到猴年马月也轮不上它
yakczh
2014-02-27 09:14:47 +08:00
@pubby 这种是通用的,我不知道7g的url里面,是不是每一条都有用

定向抓取只抓取需要的链接,根据正则来匹配url连接,一个patten对应一个parser,
貌似scrapy的rule就是这样思路

rules = [Rule(SgmlLinkExtractor(allow=['/xxx/\d+']),'parse_xxx'),
Rule(SgmlLinkExtractor(allow=['/tor/\d+']), 'parse_torrent')]

如果再进一步配置化,可以把parse函数写成数据库字段,启动时读出来动态执行, 这样只需要把parse函数当成一个功能单元测试好,更新到数据库就完了
diaoleona
2014-02-27 15:22:48 +08:00
@yakczh
'多个页面都可能有数据,每个页面有多个数据区域的话,还不知道怎么写'
没看明白你具体问题是什么?
如果担心多个页面多个数据 区域有相同的的数据的话,把你需要的数据区域都爬下来hash一下或者放在一个专门判重redis也可以在scrapy 里的中间件加一道判重过程.
最好你发个子页面的例子给看一下
yakczh
2014-02-27 16:09:41 +08:00
@diaoleona 比如京东的详情页 http://item.jd.com/1020784.html
有商品信息, 有象册,有评论 这种的是写到一个parse函数里吗,评论还可能有翻页
diaoleona
2014-02-27 16:32:02 +08:00
@yakczh
类似这种页的话一个parser专门把ur,商品信息等可以xpath的信息保存下来,
另外一个parser来抽取相关评论,翻页什么的不是问题,储存时候 评论 和这个商品的ID联系起来.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/101929

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX