V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
yakczh
V2EX  ›  Python

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

  •  
  •   yakczh · 2014-02-26 11:50:02 +08:00 · 4625 次点击
    这是一个创建于 3723 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一般抽取链接的逻辑都比较简单,有些定向爬取的的可以象 chilcat用正则匹配AddAvoidOutboundLinkPattern("xxx") 那样设置成参数 ,但是内容抽取跟实际需求相关,而且网站改版以后这部分怎么需要重写,而且一个种子站点,可能抽取的数据是多个部分,相当于一个链接抽取的处理器,和一个内容抽取的处理器,内容处理器可能是1-n个,这样设计的话比较清晰,但是一个抓取一html内容,相对于一个函数里同时获取链接和内容,这样每次分开处理应该会对性能有一定影响
    11 条回复    1970-01-01 08:00:00 +08:00
    lecher
        1
    lecher  
       2014-02-26 12:20:05 +08:00
    取决于规模,当你的规模上去之后,分开是必然的,为了保证不受网络请求延时的影响,消息通信的时候可能还要上请求队列。
    规模不大,请求不高的时候,怎么方便怎么来。只要模块接口条理清晰python重构还挺快的。
    diaoleona
        2
    diaoleona  
       2014-02-26 12:22:16 +08:00
    看你怎么设计了,我之前是爬到的response.url和 web content压缩一下放在一个数据库里,然后根据需求再做不同的抽取
    pubby
        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
    pubby
        4
    pubby  
       2014-02-26 21:45:09 +08:00
    看具体需求而定的。
    抓取规模,抓取周期,处理流程


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

    另外数据页面可能有多个区域
    yakczh
        6
    yakczh  
    OP
       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
        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要放入优先级高的队列,优先处理,要不然排到猴年马月也轮不上它
    yakczh
        8
    yakczh  
    OP
       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
        9
    diaoleona  
       2014-02-27 15:22:48 +08:00
    @yakczh
    '多个页面都可能有数据,每个页面有多个数据区域的话,还不知道怎么写'
    没看明白你具体问题是什么?
    如果担心多个页面多个数据 区域有相同的的数据的话,把你需要的数据区域都爬下来hash一下或者放在一个专门判重redis也可以在scrapy 里的中间件加一道判重过程.
    最好你发个子页面的例子给看一下
    yakczh
        10
    yakczh  
    OP
       2014-02-27 16:09:41 +08:00
    @diaoleona 比如京东的详情页 http://item.jd.com/1020784.html
    有商品信息, 有象册,有评论 这种的是写到一个parse函数里吗,评论还可能有翻页
    diaoleona
        11
    diaoleona  
       2014-02-27 16:32:02 +08:00
    @yakczh
    类似这种页的话一个parser专门把ur,商品信息等可以xpath的信息保存下来,
    另外一个parser来抽取相关评论,翻页什么的不是问题,储存时候 评论 和这个商品的ID联系起来.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3331 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 14:04 · PVG 22:04 · LAX 07:04 · JFK 10:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.