前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Scrapy中如何提高数据的插入速度

Scrapy中如何提高数据的插入速度

作者头像
小歪
发布于 2018-04-04 04:02:22
发布于 2018-04-04 04:02:22
2.7K00
代码可运行
举报
运行总次数:0
代码可运行

速度问题

最近工作中遇到这么一个问题,全站抓取时采用分布式:爬虫A与爬虫B,爬虫A给爬虫B喂饼,爬虫B由于各种原因运行的比较慢,达不到预期效果,所以必须对爬虫B进行优化。

提升Scrapy运行速度有很多方法,国外有大佬说过

Speed up web scraper

Here's a collection of things to try:

  1. use latest scrapy version (if not using already)
  2. check if non-standard middlewares are used
  3. try to increase CONCURRENT_REQUESTS_PER_DOMAIN, CONCURRENT_REQUESTS settings (docs) turn off logging LOG_ENABLED = False (docs)
  4. try yielding an item in a loop instead of collecting items into the items list and returning them use local cache DNS (see this thread)
  5. check if this site is using download threshold and limits your download speed (see this thread) log cpu and memory usage during the spider run - see if there are any problems there
  6. try run the same spider under scrapyd service
  7. see if grequests + lxml will perform better (ask if you need any help with implementing this solution)
  8. try running Scrapy on pypy, see Running Scrapy on PyPy

大致看了下,确实可以提高爬虫运行速度,但是对于海量数据(这里说的是百万级)还需要考虑一点的就是数据插入问题,这里我们使用的是 Mongo。

官方示例

让我们先从官方文档开始 Write items to MongoDB

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import pymongo

class MongoPipeline(object):

    collection_name = 'scrapy_items'

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'),
            mongo_db=crawler.settings.get('MONGO_DATABASE', 'items')
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        self.db[self.collection_name].insert_one(dict(item))
        return item

比较简单,这里插入使用的方法是 insert_one,继续文档:

insert_one(document, bypass_document_validation=False, session=None)

Insert a single document.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> db.test.count({'x': 1})
0
>>> result = db.test.insert_one({'x': 1})
>>> result.inserted_id
ObjectId('54f112defba522406c9cc208')
>>> db.test.find_one({'x': 1})
{u'x': 1, u'_id': ObjectId('54f112defba522406c9cc208')}

以前经常使用的 insert 方法,已经不被赞同

insert(doc_or_docs, manipulate=True, check_keys=True, continue_on_error=False, **kwargs)

Insert a document(s) into this collection.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DEPRECATED - Use insert_one() or insert_many() instead.

Changed in version 3.0: Removed the safe parameter. Pass w=0 for unacknowledged write operations.

insert 简单理解就是插入,把我们采集到的 item 插入到数据库,这样存在一个很严重的问题,就是去重

去重

晚上有一种很流行的写法,使用 update命令,如:

self.db[self.collection_name].update({'id': item['id']}, {'$set': dict(item)}, True)

解释为:

比较重要的一点就在于process_item,在这里使用了update方法,第一个参数传入查询条件,这里使用的是id,第二个参数传入字典类型的对象,就是我们的item,第三个参数传入True,这样就可以保证,如果查询数据存在的话就更新,不存在的话就插入。这样就可以保证去重了。

这确实是一种很简单的方法,其实原理很简单,就是在每次插入数据前,对数据库中查询,是否有该 ID,如果没有就插入,如果有就放弃。

对于数据量比较少的项目,这确实是一种很简单的方法,很简单就完成了目标。

但是,我们现在说的是百万级数据,如果每一条数据在插入前,都需要去查询该数据是否在数据库,那会多么耗时,效率会大大较低,那么还有什么好办法呢?

索引

MongoDB 索引

索引能够实现高效地查询。没有索引,MongoDB 就必须扫描集合中的所有文档,才能找到匹配查询语句的文档。这种扫描毫无效率可言,需要处理大量的数据。

索引是一种特殊的数据结构,将一小块数据集保存为容易遍历的形式。索引能够存储某种特殊字段或字段集的值,并按照索引指定的方式将字段值进行排序。

我们可以借助索引,使用 insert_one方法提高效率。代码实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MongoDBPipeline(object):
    def open_spider(self, spider):
        self.client = mongodb_client
        self.db = self.client.get_database()
        self.collection = self.db['test']
        # 添加唯一索引
        self.collection.create_index('id', unique=True)

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        try:
            self.collection.insert_one(dict(item))
            return item
        except DuplicateKeyError:
            spider.logger.debug(' duplicate key error collection')
            return item

其实很简单,就是在 open_spider先创建唯一索引,然后再插入数据。注意需要在process_item中使用异常处理,因为很有可能插入重复数据,到时候就会输出日志。

其他方法

mongo 除了 insert_one方法还有一种,insert_many

insert_many(documents, ordered=True, bypass_document_validation=False, session=None)

Insert an iterable of documents.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> db.test.count()
0
>>> result = db.test.insert_many([{'x': i} for i in range(2)])
>>> result.inserted_ids
[ObjectId('54f113fffba522406c9cc20e'), ObjectId('54f113fffba522406c9cc20f')]
>>> db.test.count()
2

这样插入的数据不再是一条,而是很多,

What's the difference between insert(), insertOne() and insertMany() methods on MongoDB

大佬有写到,可以去看看。

同时插入多条数据,减轻数据库压力。但是这个“多”到底还是多少,目前不得而知。

结语

除了更多机器和更多节点,还有很多方法可以提升 Scrapy运行速度。

今天说到的是管道阻塞问题,还有其他地方也可以优化,还需要努力。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python爬虫与算法进阶 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Python爬虫从入门到放弃(十六)之 Scrapy框架中Item Pipeline用法
当Item 在Spider中被收集之后,就会被传递到Item Pipeline中进行处理 每个item pipeline组件是实现了简单的方法的python类,负责接收到item并通过它执行一些行为,
coders
2018/01/04
1.1K0
Python爬虫从入门到放弃(十六)之 Scrapy框架中Item Pipeline用法
Scrapy 框架的使用之 Item Pipeline 的用法
Item Pipeline 的调用发生在 Spider 产生 Item 之后。当 Spider 解析完 Response 之后,Item 就会传递到 Item Pipeline,被定义的 Item Pipeline 组件会顺次调用,完成一连串的处理过程,比如数据清洗、存储等。
马修
2021/01/21
6630
[890]scrapy之pipeline的使用
scrapy的pipeline是一个非常重要的模块,主要作用是将return的items写入到数据库、文件等持久化模块,下面我们就简单的了解一下pipelines的用法。
周小董
2020/08/13
1.1K0
Scrapy(4)spider 帮助你寻找最美小姐姐
我们都知道我们平常想下载一些漂亮的图片来装饰自己的桌面,可是找到了都是需要收费的网站,真的很恼火,所以今天小编,可能要带大家实现这么一个工具,可以用来爬取某个网站的好看的图片
公众号---人生代码
2020/05/16
5150
Scrapy框架之批量下载360妹纸图
0.导语1.项目初始化2.定义存储结构3.Spider核心代码4.pipeline下载及存储5.json知识
公众号guangcity
2019/09/20
5670
Scrapy框架之批量下载360妹纸图
Scrapy+MongoDB 轻松爬取海量妹子图
【原文链接】:https://mp.weixin.qq.com/s/WIrepTu-2CGrGifLLRsHjw
Python数据科学
2018/09/14
1.7K0
Scrapy+MongoDB 轻松爬取海量妹子图
手把手教你用Scrapy爬取知乎大V粉丝列表
导读:通过获取知乎某个大V的关注列表和被关注列表,查看该大V以及其关注用户和被关注用户的详细信息,然后通过层层递归调用,实现获取关注用户和被关注用户的关注列表和被关注列表,最终实现获取大量用户信息。
IT阅读排行榜
2021/05/06
9420
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
在旅游行业和城市规划中,热门景点的数据分析具有重要意义。通过爬取景点数据并生成热力图,可以直观展示游客分布、热门区域及人流趋势,为商业决策、景区管理及智慧城市建设提供数据支持。
小白学大数据
2025/05/17
1310
使用Python和Scrapy框架进行网络爬虫的全面指南
网络爬虫是一种自动化的程序,用于从互联网上收集信息。Python是一个功能强大的编程语言,拥有许多用于网络爬虫的库和框架。其中,Scrapy是一个流行的开源网络爬虫框架,它提供了一套强大的工具和组件,使得开发和部署爬虫变得更加容易。本文将介绍如何使用Python和Scrapy框架来构建一个简单的网络爬虫。
一键难忘
2024/07/08
5460
Scrapy框架系列--数据不保存,就是耍流氓(3)
OK,通过签名两篇文章《爬虫利器初体验(1)》《听说你的爬虫又被封了?(2)》,我们初体验也过了,爬虫代码健壮性也升级为 PLUS 了。都分析到这个地步了,是不是感觉还少了点什么?对,我们还没保存数据呀?不保存,这不是瞎忙活吗?
1480
2019/08/05
9690
Scrapy框架系列--数据不保存,就是耍流氓(3)
scrapy 进阶使用
乐百川
2018/01/09
2.1K0
scrapy 进阶使用
分布式爬虫搭建系列 之三---scrapy框架初用
其次,通过我们的神器PyCharm打开我们的项目--crawlquote(也可以将PyCharm打开我们使用虚拟环境创建的项目)
wfaceboss
2019/04/08
6010
分布式爬虫搭建系列 之三---scrapy框架初用
利用 Scrapy 爬取知乎用户信息
  思路:通过获取知乎某个大V的关注列表和被关注列表,查看该大V和其关注用户和被关注用户的详细信息,然后通过层层递归调用,实现获取关注用户和被关注用户的关注列表和被关注列表,最终实现获取大量用户信息。 一、新建一个scrapy项目   scrapy startproject zhihuuser   移动到新建目录下: cd zhihuuser   新建spider项目: scrapy genspider zhihu zhihu.com 二、这里以爬取知乎大V轮子哥的用户信息来实现爬取知乎大量用户信息。 a)
希希里之海
2018/05/16
6720
Python(十六)
接下来的几篇,我们将介绍一下最流行的爬虫框架 Scrapy。本篇,我们会介绍一下 Scrapy 的基本使用。
1ess
2021/11/01
3390
Python(十六)
Python爬虫从入门到放弃(十九)之 Scrapy爬取所有知乎用户信息(下)
在上一篇文章中主要写了关于爬虫过程的分析,下面是代码的实现,完整代码在: https://github.com/pythonsite/spider items中的代码主要是我们要爬取的字段的定义 cl
coders
2018/01/04
8840
Python爬虫从入门到放弃(十九)之 Scrapy爬取所有知乎用户信息(下)
Python爬虫框架:scrapy爬取知乎数据
基础环境沿用之前的环境,只是增加了MongoDB(非关系型数据库)和PyMongo(Python 的 MongoDB 连接库),默认我认为大家都已经安装好并启动 了MongoDB 服务。
python学习教程
2019/10/22
1.5K0
Python爬虫框架:scrapy爬取知乎数据
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
在旅游行业和城市规划中,热门景点的数据分析具有重要意义。通过爬取景点数据并生成热力图,可以直观展示游客分布、热门区域及人流趋势,为商业决策、景区管理及智慧城市建设提供数据支持。
小白学大数据
2025/05/16
570
data pipeline是做什么_pycharm创建爬虫项目
爬取爱套图网图片:https://github.com/EExplode/scrapy_aitaotu
全栈程序员站长
2022/10/05
4440
Scrapy框架的使用之Scrapy入门
接下来介绍一个简单的项目,完成一遍Scrapy抓取流程。通过这个过程,我们可以对Scrapy的基本用法和原理有大体了解。 一、准备工作 本节要完成的任务如下。 创建一个Scrapy项目。 创建一个Spider来抓取站点和处理数据。 通过命令行将抓取的内容导出。 将抓取的内容保存的到MongoDB数据库。 二、准备工作 我们需要安装好Scrapy框架、MongoDB和PyMongo库。 三、创建项目 创建一个Scrapy项目,项目文件可以直接用scrapy命令生成,命令如下所示: scrapy st
崔庆才
2018/06/25
1.4K0
mongodb的基本使用以及pymong的用法
MongoDB 是由 C++ 语言编写的非关系型数据库,是一个基于分布式文件存储的开源数据库系统,其内容存储形式类似 JSON 对象,它的字段值可以包含其他文档、数组及文档数组,非常灵活。
DC童生
2019/11/27
1K0
相关推荐
Python爬虫从入门到放弃(十六)之 Scrapy框架中Item Pipeline用法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验