【Sasila】一个简单易用的爬虫框架

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

  • downloader是下载器。
  • processor是解析器。
  • scheduler是调度器。
  • pipeline是数据处理器。
  • 将下载器,解析器,调度器,数据处理器注入核心core成为spider对象。
  • 通过manager管理spider对象
  • manager透过webapi提供外部访问/控制接口

主要特点

  • 框架代码结构简单易用,易于修改。新手、老鸟皆可把控。
  • 采用gevent实现并发操作,与scrapy的twisted相比,代码更容易理解。
  • 完全模块化的设计,强大的可扩展性。
  • 使用方式和结构参考了scrapywebmagic。对有接触过这两个框架的朋友非常友好。
  • 不采用命令行来启动爬虫,方便调试。
  • 对数据的解析模块并没有集成,可以自由使用beautifulsouplxmlpyqueryhtml5lib等等各种解析器进行数据抽取。
  • 集成代理换IP功能。
  • 支持高并发采集数据。
  • 支持分布式。
  • 支持增量爬取。
  • 支持爬取js动态渲染的页面(加载SeleniumDownLoader即可)。
  • 提供webapi对爬虫进行管理、监控。
  • 提供即时爬虫的集成思路和结构。

安装

pip install sasila

准备

  • 请准备好您的redis服务器进行调度。
  • 并在settings.py文件中 写入您的redis服务器地址
REDIS_HOST = 'localhost'
REDIS_PORT = 6379

构建processor(解析器)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup as bs
from sasila.system_normal.processor.base_processor import BaseProcessor
from sasila.system_normal.downloader.http.spider_request import Request
from sasila.system_normal.spider.spider_core import SpiderCore

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

    @checkResponse
    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
  • 可以使用@checkResponse装饰器对返回的 response 进行校验并记录异常日志。你也可以定义自己的装饰器。
  • 解析函数因为使用 yield 关键字,所以是一个生成器。当 yield 返回 Request 对象,则会将 Request 对象推入调度器等待调度继续进行爬取。若 yield 不是返回 Request 对象则会进入 pipelinepipeline 将对数据进行清洗入库等操作。

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

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

class MezituProcessor(BaseProcessor):
    spider_id = 'mzitu'
    spider_name = '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)
  • 提供正则表达式提取方式:regex_str
  • 提供css选择器提取方式:css_str
  • 也可以自定义process_value来提取链接,其中process_value是一个生成器
  • 若使用此方式构造processor,请不要定义默认入口函数def process(self, response)

构建pipeline

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

from sasila.system_normal.pipeline.base_pipeline import ItemPipeline
import json

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

构建spider(爬虫对象)

  • 通过注入 processor 生成spider对象
from sasila.system_normal.spider.spider_core import SpiderCore

spider = SpiderCore(Mzi_Processor())
  • SpiderCore对象包含批下载数量 batch_size,下载间隔 time_sleep,使用代理 use_proxy 等一切必要的属性
SpiderCore(processor=None, downloader=None, use_proxy=False,scheduler=None,batch_size=None,time_sleep=None)
  • 本项目集成使用代理IP的功能,只要在构建SpiderCore时将 use_proxy 设置为 True,并在脚本同级目录下放置proxy.txt文件即可。你也可以在settings.py文件中写入代理IP文件路径。
PROXY_PATH_REQUEST = 'proxy/path'
  • proxy.txt文件中请写入代理IP,格式为:IP,端口号。若该代理IP有账号密码,在末尾追加账号密码即可。
127.0.0.1,8080
127.0.0.2,8080,user,pwd
127.0.0.3,8080,user,pwd
  • SpiderCore已经默认设置好了 downloaderscheduler,如果不满意,可以自己进行定制。

  • 可以为spider设置 downloaderpipeline 甚至 scheduler

 spider = spider.set_pipeline(ConsolePipeline())
  • 可以通过该方式启动爬虫
spider.start()
  • 也可以将spider注入manager进行管理
from sasila.system_normal.manager import manager
from sasila import system_web

manager.set_spider(spider)

system_web.start()

访问 http://127.0.0.1:5000/slow_spider/start?spider_id=mzi_spider 来启动爬虫。
访问 http://127.0.0.1:5000/slow_spider/stop?spider_id=mzi_spider 来停止爬虫。
访问 http://127.0.0.1:5000/slow_spider/detail?spider_id=mzi_spider 来查看爬虫详细信息。

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

  • 可以为downloader加载登录器(loginer),在使用downloader的时候使用loginer进行登录获取cookies,再进行爬取
  • 也可以自己定义一个cookie池,批量进行登录并将登录成功的cookies放进cookie池中随时进行取用。项目中暂时没有这些功能。欢迎pull request~

架构

  • 任务由 scheduler 发起调度,downloader 抓取网页内容, processor 执行预先编写的py脚本,输出结果或产生新的提链任务(发往 scheduler),形成闭环。
  • 每个脚本被认为是一个spider,spiderid确定一个任务。
  • downloader
    1.method, header, cookie, proxy,timeout 等等抓取调度控制。
    2.可以通过适配类似 phantomjs 的webkit引擎支持渲染。
  • processor
    1.灵活运用pyquery,beautifulsoup等解析页面。
    2.在脚本中完全控制调度抓取的各项参数。
    3.可以向后链传递信息。
    4.异常捕获。
  • scheduler
    1.任务优先级。
    2.对任务进行监控。
    3.对任务进行去重等操作。
    4.支持增量。
  • webApi
    1.对爬虫进行增删改查等操作。
非及时爬虫流程图

即时爬虫

即时爬虫是可以通过api调用,传入需要爬取的页面或者需求,即时爬取数据并返回结果。现阶段开发并不完善。仅提供思路参考。示例核心代码在 sasila.system_instant 中。

即时爬虫-获取数据流程图
即时爬虫-授权流程图

为啥叫Sasila?

作为一个wower,你可以猜到吗ヾ( ̄▽ ̄)

环境

现已支持python 3.X

联系方式

如果对使用有疑问,或者有想法,欢迎加入讨论群:602909155交流~

项目地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容