爬虫框架 Feapder 和 Scrapy 的对比分析

目录
  • 一、scrapy 分析
    • 1. 解析函数或数据入库出错,不会重试,会造成一定的数据丢失
    • 2. 运行方式,需借助命令行,不方便调试
    • 3. 入库 pipeline,不能批量入库
    • 二、scrapy-redis 分析
    • 1. redis 中的任务可读性不好
    • 2. 取任务时直接弹出,会造成任务丢失
    • 3. 去重耗内存
  • 三、feapder 分析
  • 四、三种爬虫简介
    • 1. AirSpider
    • 2. Spider
    • 3. BatchSpider
  • 五、feapder 项目结构
    • 1. feapder 部署
  • 六、采集效率测试

一、scrapy 分析

1. 解析函数或数据入库出错,不会重试,会造成一定的数据丢失

scrapy 自带的重试中间件只支持请求重试,解析函数内异常或者数据入库异常不会重试,但爬虫在请求数据时,往往会有一些意想不到的页面返回来,若我们解析异常了,这条任务岂不是丢了。

当然有些大佬可以通过一些自定义中间件的方式或者加异常捕获的方式来解决,我们这里只讨论自带的。

2. 运行方式,需借助命令行,不方便调试

若想直接运行,需编写如下文件,麻烦

from scrapy import cmdline

name = 'spider_name'
cmd = 'scrapy crawl {0}'.format(name)
cmdline.execute(cmd.split()

为什么必须通过命令行方式呢?因为 scrapy 是通过这种方式来加载项目中的 settings.py 文件的

3. 入库 pipeline,不能批量入库

class TestScrapyPipeline(object):
    def process_item(self, item, spider):
        return item

pipelines 里的 item 是一条条传过来的,没法直接批量入库,但数据量大的时候,我们往往是需要批量入库的,以节省数据库的性能开销,加快入库速度

二、scrapy-redis 分析

scrapy-redis 任务队列使用 redis 做的,初始任务存在 [spider_name]:start_urls 里,爬虫产生的子链接存在 [spider_name]:requests 下,那么我们先看下 redis 里的任务

1. redis 中的任务可读性不好

我们看下子链任务,可以看到存储的是序列化后的,这种可读性不好

2. 取任务时直接弹出,会造成任务丢失

我们分析下 scrapy-redis 几种任务队列,取任务时都是直接把任务弹出来,如果任务刚弹出来爬虫就意外退出,那刚弹出的这条任务就会丢失。

FifoQueue(先进先出队列) 使用 list 集合

PriorityQueue(优先级队列),使用 zset 集合

LifoQueue(先进后出队列),使用 list 集合

scrapy-redis 默认使用 PriorityQueue 队列,即优先级队列

3. 去重耗内存

使用 redis 的 set 集合对 request 指纹进行去重,这种面对海量数据去重对 redis 内存容量要求很高

需单独维护个下发种子任务的脚本

三、feapder 分析

feapder 内置 AirSpider 、 Spider BatchSpider 三种爬虫,AirSpider 对标 ScrapySpider 对标 scrapy-redis,BatchSpider 则是应于周期性采集的需求,如每周采集一次商品的销量等场景

上述问题解决方案:

(1)解析函数或数据入库出错,不会重试,会造成一定的数据丢失

feapder 对请求、解析、入库进行了全面的异常捕获,任何位置出现异常会自动重试请求,若有不想重试的请求也可指定

(2)运行方式,需借助命令行,不方便调试

feapder 支持直接运行,跟普通的 python 脚本没区别,可以借助 pycharm 调试。

除了断点调试,feapder 还支持将爬虫转为 Debug 爬虫,Debug 爬虫模式下,可指定请求与解析函数,生产的任务与数据不会污染正常环境

(3)入库 pipeline,不能批量入库

feapder 生产的数据会暂存内存的队列里,积攒一定量级或每 0.5 秒批量传给 pipeline,方便批量入库

def save_items(self, table, items: List[Dict]) -> bool:
    pass

这里有人会有疑问:

数据放到内存里了,会不会造成拥堵?

答:不会,这里限制了最高能积攒 5000 条的上限,若到达上限后,爬虫线程会强制将数据入库,然后再生产数据

若爬虫意外退出,数据会不会丢?

答:不会,任务会在数据入库后再删除,若意外退出了,产生这些数据的任务会重做

入库失败了怎么办?

答:入库失败,任务会重试,数据会重新入库,若失败次数到达配置的上限会报警

(4) redis 中的任务可读性不好

feapder 对请求里常用的字段没有序列化,只有那些 json 不支持的对象才进行序列化

(5) 取任务时直接弹出,会造成任务丢失

feapder 在获取任务时,没直接弹出,任务采用 redis zset 集合存储,每次只取小于当前时间搓分数的任务,同时将取到的任务分数修改为当前时间搓 +10 分钟,防止其他爬虫取到重复的任务。若爬虫意外退出,这些取到的任务其实还在任务队列里,并没有丢失

(6)去重耗内存

feapder 支持三种去重方式:

  • 内存去重:采用可扩展的 bloomfilter 结构,基于内存,去重一万条数据约 0.5 秒,一亿条数据占用内存约 285MB
  • 临时去重:采用 redis zset 集合存储数据的 md5 值,去重可指定时效性。去重一万条数据约 0.26 秒,一亿条数据占用内存约 1.43G
  • 永久去重:采用可扩展的 bloomfilter 结构,基于 redis,去重一万条数据约 0.5 秒,一亿条数据占用内存约 285 MB

(7)分布式爬虫需单独维护个下发种子任务的脚本

feapder 没种子任务和子链接的分别, yield feapder.Request 都会把请求下发到任务队列,我们可以在 start_requests 编写下发种子任务的逻辑

这里又有人会有疑问了

我爬虫启动多份时, start_requests 不会重复调用,重复下发种子任务么?

答:不会,分布式爬虫在调用 start_requests 时,会加进程锁,保证只能有一个爬虫调用这个函数。并且若任务队列中有任务时,爬虫会走断点续爬的逻辑,不会执行 start_requests

那支持手动下发任务么?

答:支持,按照 feapder 的任务格式,往 redis 里扔任务就好,爬虫支持常驻等待任务

四、三种爬虫简介

1. AirSpider

使用 PriorityQueue 作为内存任务队列,不支持分布式,示例代码

import feapder

class AirSpiderDemo(feapder.AirSpider):
    def start_requests(self):
        yield feapder.Request("https://www.baidu.com")

    def parse(self, request, response):
        print(response)

if __name__ == "__main__":
    AirSpiderDemo().start()

2. Spider

分布式爬虫,支持启多份,爬虫意外终止,重启后会断点续爬

import feapder

class SpiderDemo(feapder.Spider):
    # 自定义数据库,若项目中有setting.py文件,此自定义可删除
    __custom_setting__ = dict(
        REDISDB_IP_PORTS="localhost:6379", REDISDB_USER_PASS="", REDISDB_DB=0
    )

    def start_requests(self):
        yield feapder.Request("https://www.baidu.com")

    def parse(self, request, response):
        print(response)

if __name__ == "__main__":
    SpiderDemo(redis_key="xxx:xxx").start()

3. BatchSpider

批次爬虫,拥有分布式爬虫所有特性,支持分布式

import feapder

class BatchSpiderDemo(feapder.BatchSpider):
    # 自定义数据库,若项目中有setting.py文件,此自定义可删除
    __custom_setting__ = dict(
        REDISDB_IP_PORTS="localhost:6379",
        REDISDB_USER_PASS="",
        REDISDB_DB=0,
        MYSQL_IP="localhost",
        MYSQL_PORT=3306,
        MYSQL_DB="feapder",
        MYSQL_USER_NAME="feapder",
        MYSQL_USER_PASS="feapder123",
    )

    def start_requests(self, task):
        yield feapder.Request("https://www.baidu.com")

    def parse(self, request, response):
        print(response)

if __name__ == "__main__":
    spider = BatchSpiderDemo(
        redis_key="xxx:xxxx",  # redis中存放任务等信息的根key
        task_table="",  # mysql中的任务表
        task_keys=["id", "xxx"],  # 需要获取任务表里的字段名,可添加多个
        task_state="state",  # mysql中任务状态字段
        batch_record_table="xxx_batch_record",  # mysql中的批次记录表
        batch_name="xxx",  # 批次名字
        batch_interval=7,  # 批次周期 天为单位 若为小时 可写 1 / 24
    )

    # spider.start_monitor_task() # 下发及监控任务
    spider.start() # 采集

任务调度过程:

  1. mysql 中批量取出一批种子任务
  2. 下发到爬虫
  3. 爬虫获取到种子任务后,调度到 start_requests,拼接实际的请求,下发到 redis
  4. 爬虫从 redis 中获取到任务,调用解析函数解析数据
  5. 子链接入 redis,数据入库
  6. 种子任务完成,更新种子任务状态
  7. redis 中任务量过少,则继续从 mysql 中批量取出一批未做的种子任务下发到爬虫

封装了批次(周期)采集的逻辑,如我们指定 7 天一个批次,那么如果爬虫 3 天就将任务做完,爬虫重启也不会重复采集,而是等到第 7 天之后启动的时候才会采集下一批次。

同时批次爬虫会预估采集速度,若按照当前速度在指定的时间内采集不完,会发出报警

五、feapder 项目结构

上述的三种爬虫例子修改配置后可以直接运行,但对于大型项目,可能会有就好多爬虫组成。feapder 支持创建项目,项目结构如下:

main.py 为启动入口

1. feapder 部署

feapder 有对应的管理平台 feaplat ,当然这个管理平台也支持部署其他脚本

在任务列表里配置启动命令,调度周期以及爬虫数等。 爬虫数 这个对于分布式爬虫是非常爽的,可一键启动几十上百份爬虫,再也不需要一个个部署了

-w1791:

任务启动后,可看到实例及实时日志

-w1785:

爬虫监控面板可实时看到爬虫运行情况,监控数据保留半年,滚动删除

六、采集效率测试

请求百度 1 万次,线程都开到 300,测试耗时

scrapy:

class BaiduSpider(scrapy.Spider):
    name = 'baidu'
    allowed_domains = ['baidu.com']
    start_urls = ['https://baidu.com/'] * 10000

    def parse(self, response):
        print(response)

结果:

{'downloader/request_bytes': 4668123,
 'downloader/request_count': 20002,
 'downloader/request_method_count/GET': 20002,
 'downloader/response_bytes': 17766922,
 'downloader/response_count': 20002,
 'downloader/response_status_count/200': 10000,
 'downloader/response_status_count/302': 10002,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2021, 9, 13, 12, 22, 26, 638611),
 'log_count/DEBUG': 20003,
 'log_count/INFO': 9,
 'memusage/max': 74240000,
 'memusage/startup': 58974208,
 'response_received_count': 10000,
 'scheduler/dequeued': 20002,
 'scheduler/dequeued/memory': 20002,
 'scheduler/enqueued': 20002,
 'scheduler/enqueued/memory': 20002,
 'start_time': datetime.datetime(2021, 9, 13, 12, 19, 58, 489472)}

耗时:148.149139 秒

feapder:

import feapder
import time

class AirSpiderDemo(feapder.AirSpider):
    def start_requests(self):
        for i in range(10000):
            yield feapder.Request("https://www.baidu.com")

    def parse(self, request, response):
        print(response)

    def start_callback(self):
        self.start_time = time.time()

    def end_callback(self):
        print("耗时:{}".format(time.time() - self.start_time))

if __name__ == "__main__":
    AirSpiderDemo(thread_count=300).start()

结果:耗时:136.10122799873352

总结:

本文主要分析了 scrapy scrapy-redis 的痛点以及 feapder 是如何解决的,当然 scrapy 也有优点,比如社区活跃、中间件灵活等。但在保证数据及任务不丢的场景,报警监控等场景 feapder 完胜 scrapy 。并且 feapder 是基于实际业务,做过大大小小 100 多个项目,耗时 5 年打磨出来的,因此可满足绝大多数爬虫需求

效率方面,请求百度 1 万次,同为 300 线程的情况下,feapder 耗时 136 秒,scrapy 耗时 148 秒,算上网络的波动,其实效率差不多。

到此这篇关于爬虫框架 Feapder Scrapy 的对比分析的文章就介绍到这了,更多相关爬虫框架 Feapder Scrapy 的对比内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python之Scrapy爬虫框架安装及简单使用详解

    题记:早已听闻python爬虫框架的大名.近些天学习了下其中的Scrapy爬虫框架,将自己理解的跟大家分享.有表述不当之处,望大神们斧正. 一.初窥Scrapy Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. 其最初是为了页面抓取(更确切来说,网络抓取)所设计的, 也可以应用在获取API所返回的数据(例如Amazon Associates Web Services) 或者通用的网络爬虫. 本文档将通过介绍Sc

  • 上手简单,功能强大的Python爬虫框架——feapder

    简介 feapder 是一款上手简单,功能强大的Python爬虫框架,使用方式类似scrapy,方便由scrapy框架切换过来,框架内置3种爬虫: AirSpider爬虫比较轻量,学习成本低.面对一些数据量较少,无需断点续爬,无需分布式采集的需求,可采用此爬虫. Spider是一款基于redis的分布式爬虫,适用于海量数据采集,支持断点续爬.爬虫报警.数据自动入库等功能 BatchSpider是一款分布式批次爬虫,对于需要周期性采集的数据,优先考虑使用本爬虫. feapder除了支持断点续爬.数

  • Python使用Scrapy爬虫框架全站爬取图片并保存本地的实现代码

    大家可以在Github上clone全部源码. Github:https://github.com/williamzxl/Scrapy_CrawlMeiziTu Scrapy官方文档:http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html 基本上按照文档的流程走一遍就基本会用了. Step1: 在开始爬取之前,必须创建一个新的Scrapy项目. 进入打算存储代码的目录中,运行下列命令: scrapy startproject CrawlMe

  • Python爬虫框架之Scrapy中Spider的用法

    Spider类定义了如何爬取某个(或某些)网站.包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item).换句话说,Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方. 对spider来说,爬取的循环类似下文: 1.以初始的URL初始化Request,并设置回调函数.当该request下载完毕并返回时,将生成response,并作为参数传给该回调函数.spider中初始的request是通过调用start_requests()来获取的.sta

  • python爬虫框架feapde的使用简介

    1. 前言 大家好,我是安果! 众所周知,Python 最流行的爬虫框架是 Scrapy,它主要用于爬取网站结构性数据 今天推荐一款更加简单.轻量级,且功能强大的爬虫框架:feapder 项目地址: https://github.com/Boris-code/feapder 2. 介绍及安装 和 Scrapy 类似,feapder 支持轻量级爬虫.分布式爬虫.批次爬虫.爬虫报警机制等功能 内置的 3 种爬虫如下: AirSpider 轻量级爬虫,适合简单场景.数据量少的爬虫 Spider 分布式

  • python Scrapy爬虫框架的使用

    导读:如何使用scrapy框架实现爬虫的4步曲?什么是CrawSpider模板?如何设置下载中间件?如何实现Scrapyd远程部署和监控?想要了解更多,下面让我们来看一下如何具体实现吧! Scrapy安装(mac) pip install scrapy 注意:不要使用commandlinetools自带的python进行安装,不然可能报架构错误:用brew下载的python进行安装. Scrapy实现爬虫 新建爬虫 scrapy startproject demoSpider,demoSpide

  • python3 Scrapy爬虫框架ip代理配置的方法

    什么是Scrapy? Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍.所谓的框架就是一个已经被集成了各种功能(高性能异步下载,队列,分布式,解析,持久化等)的具有很强通用性的项目模板.对于框架的学习,重点是要学习其框架的特性.各个功能的用法即可. 一.背景 在做爬虫项目的过程中遇到ip代理的问题,网上搜了一些,要么是用阿里云的ip代理,要么是搜一些网上现有的ip资源,然后配置在setting文件中.这两个方法都存在一些问题. 1.阿里云ip代理方法,网上大

  • 详解Python的爬虫框架 Scrapy

    网络爬虫,是在网上进行数据抓取的程序,使用它能够抓取特定网页的HTML数据.虽然我们利用一些库开发一个爬虫程序,但是使用框架可以大大提高效率,缩短开发时间.Scrapy是一个使用Python编写的,轻量级的,简单轻巧,并且使用起来非常的方便. 一.概述 下图显示了Scrapy的大体架构,其中包含了它的主要组件及系统的数据处理流程(绿色箭头所示).下面就来一个个解释每个组件的作用及数据的处理过程(注:图片来自互联网). 二.组件 1.Scrapy Engine(Scrapy引擎) Scrapy引擎

  • Python爬虫框架Scrapy实例代码

    目标任务:爬取腾讯社招信息,需要爬取的内容为:职位名称,职位的详情链接,职位类别,招聘人数,工作地点,发布时间. 一.创建Scrapy项目 scrapy startproject Tencent 命令执行后,会创建一个Tencent文件夹,结构如下 二.编写item文件,根据需要爬取的内容定义爬取字段 # -*- coding: utf-8 -*- import scrapy class TencentItem(scrapy.Item): # 职位名 positionname = scrapy.

  • Python爬虫框架-scrapy的使用

    Scrapy Scrapy是纯python实现的一个为了爬取网站数据.提取结构性数据而编写的应用框架. Scrapy使用了Twisted异步网络框架来处理网络通讯,可以加快我们的下载速度,并且包含了各种中间件接口,可以灵活的完成各种需求 1.安装 sudo pip3 install scrapy 2.认识scrapy框架 2.1 scrapy架构图 Scrapy Engine(引擎): 负责Spider.ItemPipeline.Downloader.Scheduler中间的通讯,信号.数据传递

  • 一文读懂python Scrapy爬虫框架

    Scrapy是什么? 先看官网上的说明,http://scrapy-chs.readthedocs.io/zh_CN/latest/intro/overview.html Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架.可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. 其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫. S

随机推荐