V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
wangleineo
V2EX  ›  问与答

怎样设计一个分布式的爬虫服务?

  •  
  •   wangleineo · 2016-02-22 11:31:13 +08:00 · 6149 次点击
    这是一个创建于 3196 天前的主题,其中的信息可能已经有所发展或是发生改变。

    爬虫程序有一个很大的问题,就是服务端会限制一个 IP 的请求频率,甚至封禁一个 IP 。解决这个问题的一个办法就是用多个不同网络的主机或代理来发出请求(同时限制频率),最后再把爬取的结果汇总。

    Scrapy Cloud 就是一个这样的分布式服务: https://www.scrapinghub.com/, 是 scrapy 的作者们写的一个商业化的 SaaS 服务,核心非开源。

    问题是:在接收到一个爬虫请求以后,怎样分配爬取链接到各个 worker 上面?这个问题似乎比较复杂,因为需要爬取的链接不是一个线性的列表,而是一个图结构(图中每个节点是一个需要爬取的链接),在预先只有图的根节点的情况下,怎样把爬取任务分配给各个 Worker 节点,又使得各个节点的任务尽量平均又不重合呢?

    比如一个策略是,从根节点展开第一个层次的所有链接,然后把这些链接平均分配到各个 worker 开始爬取,但是有可能第二层有很多个公共的链接,各个 worker 就会重复很多爬取动作。

    有什么好的想法吗?

    16 条回复    2016-09-09 09:37:11 +08:00
    gouwudang
        1
    gouwudang  
       2016-02-22 12:15:09 +08:00
    楼主对这方面感兴趣欢迎来我司,我们在找 Python 工程师加盟,更好的解决这方面的问题
    yangqi
        2
    yangqi  
       2016-02-22 12:41:19 +08:00
    中间加一层 scraper ,专门爬链接,然后再分配给 worker 抓取页面
    knightdf
        3
    knightdf  
       2016-02-22 12:46:46 +08:00
    我是写了一个基于 redis 的 bloomfilter 来做, master 节点只分配入口 url ,集群子节点只管抓取,管理全部 master 节点来管理,对 子节点定时关机换机器。跑在 AWS 上
    yixiang
        4
    yixiang  
       2016-02-22 12:48:32 +08:00   ❤️ 1
    无经验。随意想到的思路:
    多个 worker ,一个 center , center 负责分配任务,爬虫爬完后把结果返回给 center ,只在 center 这里存储整个图和工作怎样分配。

    其实类似于……
    一个爬虫+一堆匿名代理,请求一个就换一个代理。

    估计实际环境中会遇到许多问题。
    wangleineo
        5
    wangleineo  
    OP
       2016-02-22 13:00:12 +08:00
    @gouwudang IT 桔子上没看到你们融资啊,是已经闷声发大财了吗?

    @yangqi 这样的话, scraper 需要访问所有链接了,还是很容易被禁。 worker 只是分担了抓取动作本身。
    wangleineo
        6
    wangleineo  
    OP
       2016-02-22 13:02:50 +08:00
    @knightdf 那 bloomfilter 是做什么的?看一个 url 有没有被爬过?
    Kirscheis
        7
    Kirscheis  
       2016-02-22 14:05:29 +08:00
    这样是否可行?
    worker 首先 parse ,之后把抽取的 url 返回给 master ,然后从 master 的 waiting list 领取下一个 request 。
    master 维护一个保存着爬过的 url 的库, worker 返回的所有链接用 bloomfilter 快速检查是否爬过,然后把没爬过的加入 waiting list 。
    sohoer
        8
    sohoer  
       2016-02-22 14:05:37 +08:00
    一个 Crawler 负责任务调度,将需要采集网址通过负载均衡的方式分发给其它 Crawler
    knightdf
        9
    knightdf  
       2016-02-22 15:09:13 +08:00
    @wangleineo 你不是要解决 URL 分配的问题么,这样我的子节点就只用接受根节点这一个 URL 任务了
    izoabr
        10
    izoabr  
       2016-02-22 15:28:18 +08:00
    要分是不是得 hadoop 了?
    chinajik
        11
    chinajik  
       2016-02-22 15:49:45 +08:00
    客户机方面:
    ip ban 的话就用 ADSL 服务器.
    Captcha 用 selenium 截图用第三方平台解析

    消费端:
    走队列建索引, 基本数据传输走 websocket 请求 keepalive 穿透性强



    再写些拨号脚本,重启脚本的,自动阀值调控, 多线程就不用讲了。

    爬虫对实时性要求高的,基本看被爬的服务器的阀值峰值,基本上核心价值观就是你不影响他线上业务,一定程度的爬虫运维是睁一只眼闭一只眼的...
    wangleineo
        12
    wangleineo  
    OP
       2016-02-22 16:05:31 +08:00
    @Kirscheis
    @knightdf
    scrapinghub 就是这么做的: https://github.com/scrapinghub/frontera
    这个组件的功能就是根据一些策略给 worker 分配爬取任务, worker 爬到新的 url 再提交给 frontera.
    knightdf
        13
    knightdf  
       2016-02-22 16:35:20 +08:00
    @wangleineo 对的,这样设计集群靠谱点, slave 只做抓取的任务
    yangqi
        14
    yangqi  
       2016-02-22 22:28:16 +08:00
    @wangleineo scraper 也可以是分布式的啊
    SlipStupig
        15
    SlipStupig  
       2016-02-23 00:50:46 +08:00
    你如果是遇到被 ban 掉,你解决方案肯定不是去搞分布式,几种方案
    1.伪造 x-forward-for 头部去欺骗,不一定能成功
    2.去用 http 代理,一些网站会拉黑一些代理
    3.用 tor 节点
    4.adsl 重新拨号,这个不靠谱, adsl 的 ip 量有限,而且不一定恰好遇到 ip 释放

    结论就是,花点钱去买代理吧
    ssllff123
        16
    ssllff123  
       2016-09-09 09:37:11 +08:00
    @knightdf scrapy 实现了这个功能。 scrapy-redis 但是我正在学习中
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2810 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:06 · PVG 08:06 · LAX 16:06 · JFK 19:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.