- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章爬虫框架 Feapder 和 Scrapy 的对比分析由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
scrapy 自带的重试中间件只支持请求重试,解析函数内异常或者数据入库异常不会重试,但爬虫在请求数据时,往往会有一些意想不到的页面返回来,若我们解析异常了,这条任务岂不是丢了.
当然有些大佬可以通过一些自定义中间件的方式或者加异常捕获的方式来解决,我们这里只讨论自带的.
若想直接运行,需编写如下文件,麻烦 。
from scrapy import cmdlinename = "spider_name"cmd = "scrapy crawl {0}".format(name)cmdline.execute(cmd.split()
为什么必须通过命令行方式呢?因为 scrapy 是通过这种方式来加载项目中的 settings.py 文件的 。
class TestScrapyPipeline(object): def process_item(self, item, spider): return item
pipelines 里的 item 是一条条传过来的,没法直接批量入库,但数据量大的时候,我们往往是需要批量入库的,以节省数据库的性能开销,加快入库速度 。
scrapy-redis 任务队列使用 redis 做的,初始任务存在 [spider_name]:start_urls 里,爬虫产生的子链接存在 [spider_name]:requests 下,那么我们先看下 redis 里的任务 。
我们看下子链任务,可以看到存储的是序列化后的,这种可读性不好 。
我们分析下 scrapy-redis 几种任务队列,取任务时都是直接把任务弹出来,如果任务刚弹出来爬虫就意外退出,那刚弹出的这条任务就会丢失.
FifoQueue(先进先出队列) 使用 list 集合 。
PriorityQueue(优先级队列),使用 zset 集合 。
。
LifoQueue(先进后出队列),使用 list 集合 。
scrapy-redis 默认使用 PriorityQueue 队列,即优先级队列 。
使用 redis 的 set 集合对 request 指纹进行去重,这种面对海量数据去重对 redis 内存容量要求很高 。
需单独维护个下发种子任务的脚本 。
feapder 内置 AirSpider 、 Spider 、 BatchSpider 三种爬虫,AirSpider 对标 Scrapy,Spider 对标 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 秒,一亿条数据占用内存约 285MBredis
的 zset
集合存储数据的 md5 值,去重可指定时效性。去重一万条数据约 0.26 秒,一亿条数据占用内存约 1.43Gbloomfilter
结构,基于 redis,去重一万条数据约 0.5 秒,一亿条数据占用内存约 285 MB(7)分布式爬虫需单独维护个下发种子任务的脚本 。
feapder 没种子任务和子链接的分别, yield feapder.Request 都会把请求下发到任务队列,我们可以在 start_requests 编写下发种子任务的逻辑 。
这里又有人会有疑问了 。
我爬虫启动多份时, start_requests 不会重复调用,重复下发种子任务么?
答:不会,分布式爬虫在调用 start_requests 时,会加进程锁,保证只能有一个爬虫调用这个函数。并且若任务队列中有任务时,爬虫会走断点续爬的逻辑,不会执行 start_requests 。
那支持手动下发任务么?
答:支持,按照 feapder 的任务格式,往 redis 里扔任务就好,爬虫支持常驻等待任务 。
使用 PriorityQueue 作为内存任务队列,不支持分布式,示例代码 。
import feapderclass 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()
分布式爬虫,支持启多份,爬虫意外终止,重启后会断点续爬 。
import feapderclass 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()
批次爬虫,拥有分布式爬虫所有特性,支持分布式 。
import feapderclass 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() # 采集
任务调度过程:
mysql
中批量取出一批种子任务 start_requests
,拼接实际的请求,下发到 redis
redis
中获取到任务,调用解析函数解析数据redis
,数据入库redis
中任务量过少,则继续从 mysql
中批量取出一批未做的种子任务下发到爬虫封装了批次(周期)采集的逻辑,如我们指定 7 天一个批次,那么如果爬虫 3 天就将任务做完,爬虫重启也不会重复采集,而是等到第 7 天之后启动的时候才会采集下一批次.
同时批次爬虫会预估采集速度,若按照当前速度在指定的时间内采集不完,会发出报警 。
上述的三种爬虫例子修改配置后可以直接运行,但对于大型项目,可能会有就好多爬虫组成。feapder 支持创建项目,项目结构如下:
main.py 为启动入口 。
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 feapderimport timeclass 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 的对比内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
最后此篇关于爬虫框架 Feapder 和 Scrapy 的对比分析的文章就讲到这里了,如果你想了解更多关于爬虫框架 Feapder 和 Scrapy 的对比分析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我刚刚继承了一个旧的 PostgreSQL 安装,需要进行一些诊断以找出该数据库运行缓慢的原因。在 MS SQL 上,您可以使用 Profiler 等工具来查看正在运行的查询,然后查看它们的执行计划。
将目标从Analytics(分析)导入到AdWords中,然后在Analytics(分析)中更改目标条件时,是否可以通过更改将目标“重新导入”到AdWords,还是可以自动选择? 最佳答案 更改目标值
我正在使用google analytics api来获取数据。我正在获取数据,但我想验证两个参数,它们在特定日期范围内始终为0。我正在获取['ga:transactions']和['ga:goalCo
我使用Google API从Google Analytics(分析)获取数据,但指标与Google Analytics(分析)的网络界面不同。 即:我在2015年3月1日获得数据-它返回综合浏览量79
我在我的Web应用程序中使用sammy.js进行剔除。我正在尝试向其中添加Google Analytics(分析)。我很快找到了following plugin来实现页面跟踪。 我按照步骤操作,页面如
当使用 Xcode 分析 (product>analyze) 时,有没有办法忽略给定文件中的任何错误? 例如编译指示之类的? 我们只想忽略第三方代码的任何警告,这样当我们的代码出现问题时,它对我们
目录 EFK 1. 日志系统 2. 部署ElasticSearch 2.1 创建handless服务 2.2 创建s
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
GCC/G++ 是否有可用于输出分析的选项? 能够比较以前的代码与新代码之间的差异(大小、类/结构的大小)将很有用。然后可以将它们与之前的输出进行比较以进行比较,这对于许多目的都是有用的。 如果没有此
我正在浏览 LYAH,并一直在研究处理列表时列表理解与映射/过滤器的使用。我已经分析了以下两个函数,并包含了教授的输出。如果我正确地阅读了教授的内容,我会说 FiltB 的运行速度比 FiltA 慢很
在 MySQL 中可以使用 SET profiling = 1; 设置分析 查询 SHOW PROFILES; 显示每个查询所用的时间。我想知道这个时间是只包括服务器的执行时间还是还包括将结果发送到前
我用 Python 编写了几个用于生成阶乘的模块,我想测试运行时间。我找到了一个分析示例 here我使用该模板来分析我的模块: import profile #fact def main():
前几天读了下mysqld_safe脚本,个人感觉还是收获蛮大的,其中细致的交代了MySQL数据库的启动流程,包括查找MySQL相关目录,解析配置文件以及最后如何调用mysqld程序来启动实例等,有着
上一篇:《人工智能大语言模型起源篇,低秩微调(LoRA)》 (14)Rae 和同事(包括78位合著者!)于2022年发表的《Scaling Language Models: Methods, A
1 内网基础 内网/局域网(Local Area Network,LAN),是指在某一区域内有多台计算机互联而成的计算机组,组网范围通常在数千米以内。在局域网中,可以实现文件管理、应用软件共享、打印机
1 内网基础 内网/局域网(Local Area Network,LAN),是指在某一区域内有多台计算机互联而成的计算机组,组网范围通常在数千米以内。在局域网中,可以实现文件管理、应用软件共享、打印机
我有四列形式的数据。前三列代表时间,value1,value 2。第四列是二进制,全为 0 或 1。当第四列中对应的二进制值为0时,有没有办法告诉excel删除时间、值1和值2?我知道这在 C++ 或
我正在运行一个进行长时间计算的 Haskell 程序。经过一些分析和跟踪后,我注意到以下内容: $ /usr/bin/time -v ./hl test.hl 9000045000050000 Com
我有一个缓慢的 asp.net 程序正在运行。我想分析生产服务器以查看发生了什么,但我不想显着降低生产服务器的速度。 一般而言,配置生产盒或仅本地开发盒是标准做法吗?另外,您建议使用哪些程序来实现这一
我目前正在尝试分析 Haskell 服务器。服务器永远运行,所以我只想要一个固定时间的分析报告。我尝试只运行该程序 3 分钟,然后礼貌地要求它终止,但不知何故,haskell 分析器不遵守术语信号,并
我是一名优秀的程序员,十分优秀!