fetchman PyPI Version Build Status Coverage Status

  现在有很多爬虫框架,比如scrapywebmagicpyspider都可以在爬虫工作中使用,也可以直接通过requests+beautifulsoup来写一些个性化的小型爬虫脚本。但是在实际爬取过程当中,爬虫框架各自有优势和缺陷。比如scrapy,它的功能强大,但过于强大的功能也许反而让新手无所适从,并且它采用twisted异步框架开发,对新手来说源码难以理解,项目难于调试。所以我模仿这些爬虫框架的优势,以尽量简单的原则,搭配gevent(实际上是grequests)开发了这套轻量级爬虫框架。

主要特点

安装

pip install fetchman

准备

class Mzi_Processor(BaseProcessor): spider_id = 'mzi_spider' allowed_domains = ['mzitu.com'] start_requests = [Request(url='http://www.mzitu.com/', priority=0)]

@check
def process(self, response):
    soup = bs(response.m_response.content, 'lxml')
    print soup.title.string
    href_list = soup.select('a')
    for href in href_list:
        yield Request(url=response.nice_join(href['href']))
**写法与scrapy几乎一样**

* 所有的解析器都继承自 *BaseProcessor* ,默认入口解析函数为def process(self, response)。
* 为该解析器设置spider_id和spider_name,以及限定域名。
* 初始爬取请求为 *start_requests*,构建Request对象,该对象支持GET、POST方法,支持优先级,设置回调函数等等所有构建request对象的一切属性。默认回调函数为 *process*。
* 可以使用@check装饰器对返回的 *response* 进行校验并记录异常日志。你也可以定义自己的装饰器。
* 解析函数因为使用 *yield* 关键字,所以是一个生成器。当 *yield* 返回 *Request* 对象,则会将 *Request* 对象推入调度器等待调度继续进行爬取。若 *yield* 不是返回 *Request* 对象则会进入 *pipeline* , *pipeline* 将对数据进行清洗入库等操作。

**与scrapy相似,fetchman同样提供*LinkExtractor的*方式来提取链接,以下是用*LinkExtractor*的方式构造*processor*下载妹子图的示例**

```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from fetchman.processor.base_processor import BaseProcessor, Rule, LinkExtractor
from fetchman.downloader.http.spider_request import Request
import os
import uuid

class MezituProcessor(BaseProcessor):
    spider_id = 'mzitu'
    allowed_domains = ['mzitu.com', 'meizitu.net']
    start_requests = [Request(url='http://www.mzitu.com/xinggan/')]

    rules = (
        Rule(LinkExtractor(regex_str=r"http://i.meizitu.net/\d{4}/\d{2}/[0-9a-z]+.jpg"),callback="save", priority=3),
        Rule(LinkExtractor(regex_str=r"http://www.mzitu.com/\d+"), priority=1),
        Rule(LinkExtractor(regex_str=r"http://www.mzitu.com/\d+/\d+"), priority=2),
        Rule(LinkExtractor(regex_str=r"http://www.mzitu.com/xinggan/page/\d+"), priority=0),
    )

    def save(self, response):
        if response.m_response:
            if not os.path.exists("img"):
                os.mkdir("img")
            with open("img/" + str(uuid.uuid1()) + ".jpg", 'wb') as fs:
                fs.write(response.m_response.content)
                print("download success!")

LinkExtractor的构造方式为

LinkExtractor(regex_str=None, css_str=None, process_value=None)

构建pipeline

该pipeline获取数据后将数据转为json格式,并输出到屏幕

from fetchman.pipeline.base_pipeline import ItemPipeline

class ConsolePipeline(ItemPipeline):
    def process_item(self, item):
        print json.dumps(item).decode("unicode-escape")

构建spider(爬虫对象)

spider = SpiderCore(Mzi_Processor())

* RequestSpider对象包含批下载数量 *batch_size*,下载间隔 *time_sleep*,使用代理 *use_proxy* 等一切必要的属性
```python
SpiderCore(processor=None, downloader=None, use_proxy=False,scheduler=None,batch_size=None,time_sleep=None)

针对需要登录才能爬取的处理办法

架构

jichu