Scrapy(五) - Extension的使用

介绍

Scrapy 提供了一个Extension机制,可以让我们添加和扩展一些自定义的功能。利用Extension 我们可以注册一些
处理方法并监听Scrapy 运行过程中的各个信号,做到某个事件发生的时候执行我们自定义的方法

Scrapy 已经内置了一些Extension:

  • LogStats:用于记录一些基本的爬取信息,比如爬取的页面数量,提取的item数量等
  • CoreStats:用于统计爬取过程中的核心统计信息,如开始爬取时间,爬取结束时间等。

通过如下配置可以开启这两个Extension

# settings.py
EXTENSIONS = {
  'scrapy.extensions.corestats.CoreStats': 500,
  'scrapy.extensions.telnet.TelnetConsole': 501
}

另外我们也可以实现自定义的Extension,实现过程其实非常简单,主要分为:

  • 实现一个Python类,然后实现对应的处理方法,如实现一个spider_opened方法用于处理Spider开始爬取时执行的操作,
    可以接收一个spider参数并对其进行操作
  • 定义from_crawler类方法,其第一个参数是cls 类对象,第二个参数是crawler。利用crawler的signals对象将Scrapy
    的各个信号和已经定义的处理方法关联起来

实战

1.利用 Flask 搭建一个简单的 web 服务器,来接收 来自 Scrapy 相应事件触发的请求:

from flask import Flask,request,jsonify
from loguru import logger


app = Flask(__name__)


@app.route('/notify', methods=['POST'])
def receive():
    post_data = request.get_json()
    event = post_data.get('event')
    data  = post_data.get('data')
    logger.debug(f'receive event:{event},data:{data}')
    return jsonify(status='success')

if __name__ == '__main__':
    app.run(debug=True,host='127.0.0.1',port=5000)

2.新增extensions.py

# @Time: 2022/12/21 10:40
# @Authot: zzc
# @Project: scrapyitempipelinedemo
# @File:extensions.py.py
from scrapy import signals
import requests


notification_url = 'http://127.0.0.1:5000/notify'


class NotificationExtension(object):

    def spider_opened(self, spider):
        """
        爬取开始时的处理
        :param spider:
        :return:
        """
        requests.post(notification_url, json={
            'event':'spider_opened',
            'data':{'spider_name':spider.name}
        })

    def spider_closed(self, spider):
        """
        爬取结束时的处理
        :param spider: 
        :return: 
        """
        requests.post(notification_url,json={
            'event':'SPIDER_CLOSED',
            'data':{'spider_name':spider.name}
        })

    def item_scraped(self, item, spider):
        """
        爬取到item的处理
        :param item: 
        :param spider: 
        :return: 
        """
        requests.post(notification_url,json={
            'event':'ITEM_SCRAPED',
            'data':{'spider_name':spider.name,'item': dict(item)}
        })
        
        
    @classmethod
    def from_crawler(cls,crawler):
        ext = cls()
        crawler.signals.connect(ext.spider_opened,signal=signals.spider_opened)
        crawler.signals.connect(ext.spider_closed,signal=signals.spider_closed)
        crawler.signals.connect(ext.item_scraped,signal=signals.item_scraped)
        return ext

执行scrapy 后,Flask 服务输出:

SPIDER_CLOSED :

Crawler 对象里面有一个子对象叫做signals,通过调用signals 对象的connect方法,我们可以将Scrapy运行过程中
的某个信号和我们自定义的处理方法关联起来。这样在某个事件发生的时候,被关联的处理方法就会被调用。

posted @ 2022-12-21 17:09  chuangzhou  阅读(123)  评论(0编辑  收藏  举报