[Sasila] 一个简单易用的爬虫框架 - V2EX
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
darksand
V2EX    Python

[Sasila] 一个简单易用的爬虫框架

  •  1
     
  •   darksand 2017-07-12 14:01:31 +08:00 3703 次点击
    这是一个创建于 3082 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在有很多爬虫框架,比如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"),callbak="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,你可以猜到吗( ̄ ̄)

    环境

    暂时只支持 python2.7,其它版本还没有测试过。。

    联系方式

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

    项目地址

    7 条回复    2017-07-13 16:25:37 +08:00
    NaVient
        1
    NaVient  
       2017-07-12 14:24:54 +08:00   1
    支持,已 star
    ikeeper
        2
    ikeeper  
       2017-07-12 17:22:46 +08:00   1
    支持,已 star
    tedchen
        3
    tedchen  
       2017-07-12 19:48:24 +08:00
    支持,已 star
    cxd44
        4
    cxd44  
       2017-07-12 20:39:06 +08:00 via Android
    支持
    darksand
        5
    darksand  
    OP
       2017-07-12 22:57:18 +08:00 via iPhone
    @cxd44 谢谢!
    darksand
        6
    darksand  
    OP
       2017-07-12 22:57:48 +08:00 via iPhone
    @tedchen 谢谢!
    yangyaofei
        7
    yangyaofei  
       2017-07-13 16:25:37 +08:00 via Android
    正在用 pyspider 做项目,不知道这个和 pyspider 比起来优势是啥?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2801 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 20ms UTC 02:54 PVG 10:54 LAX 18:54 JFK 21:54
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86