1
lecher 2014-02-26 12:20:05 +08:00
取决于规模,当你的规模上去之后,分开是必然的,为了保证不受网络请求延时的影响,消息通信的时候可能还要上请求队列。
规模不大,请求不高的时候,怎么方便怎么来。只要模块接口条理清晰python重构还挺快的。 |
2
diaoleona 2014-02-26 12:22:16 +08:00
看你怎么设计了,我之前是爬到的response.url和 web content压缩一下放在一个数据库里,然后根据需求再做不同的抽取
|
3
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 |
4
pubby 2014-02-26 21:45:09 +08:00
看具体需求而定的。
抓取规模,抓取周期,处理流程 如果是一次性的,怎么简单怎么来,想这么多..... |
5
yakczh OP 你说的这种是链接专门在一个页面,数据在另一个页面, 假如一个页面同时有数据和链接呢?
另外数据页面可能有多个区域 |
6
yakczh OP @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,这样各收集各的,两种都支持更灵活一些 |
7
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要放入优先级高的队列,优先处理,要不然排到猴年马月也轮不上它 |
8
yakczh OP @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函数当成一个功能单元测试好,更新到数据库就完了 |
9
diaoleona 2014-02-27 15:22:48 +08:00
@yakczh
'多个页面都可能有数据,每个页面有多个数据区域的话,还不知道怎么写' 没看明白你具体问题是什么? 如果担心多个页面多个数据 区域有相同的的数据的话,把你需要的数据区域都爬下来hash一下或者放在一个专门判重redis也可以在scrapy 里的中间件加一道判重过程. 最好你发个子页面的例子给看一下 |
10
yakczh OP |
11
diaoleona 2014-02-27 16:32:02 +08:00
|