Scrapy爬虫框架-自定义中间件

简介: Scrapy爬虫框架-自定义中间件

Scrapy爬虫框架-自定义中间件
Scrapy中内置了多个中间件,不过在多数情况下开发者都会选择创建一个属于自己的中间件,这样既可以满足自己的开发需求,还可以节省很多开发时间。在实现自定义中间件时需要重写部分方法,因为Scrapy引擎需要根据这些方法名来执行并处理,如果没有重写这些方法,Scrapy的引擎将会按照原有的方法执行,从而失去自定义中间件的意义。

1.1 设置固定请求头
示例代码如下:

#_*_coding:utf-8_*_
# 作者      :liuxiaowei
# 创建时间   :2/18/22 10:45 AM
# 文件      :设置请求头.py
# IDE      :PyCharm

import scrapy
import requests
class HeaderSpider(scrapy.Spider):
    # 定义爬虫名称
    name = 'header'

    def start_requests(self):
        # 设置固定的请求头
        self.headers = {
   
                    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"
                        }
        return [scrapy.Request('http://httpbin.org/get', headers=self.headers, callback=self.parse)]

    # 响应信息
    def parse(self, response):
        print(response.text)

# 导入CrawlProcess类
from scrapy.crawler import CrawlerProcess
# 导入获取项目设置信息
from scrapy.utils.project import get_project_settings

# 程序入口
if __name__ == "__main__":
  # 创建CrawlProcess类对象并传入项目设置信息参数
  process = CrawlerProcess(get_project_settings())
  # 设置需要启动的爬虫名称
  process.crawl('header')
  # 启动爬虫
  process.start(

程序运行结果如下:

2022-02-18 15:02:40 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
2022-02-18 15:02:42 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://httpbin.org/robots.txt> (referer: None)
2022-02-18 15:02:42 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://httpbin.org/get> (referer: None)
{
   
  "args": {
   }, 
  "headers": {
   
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 
    "Accept-Encoding": "gzip, deflate", 
    "Accept-Language": "en", 
    "Host": "httpbin.org", 
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", 
    "X-Amzn-Trace-Id": "Root=1-620f4492-522c108346226f8936ae0be6"
  }, 
  "origin": "122.143.185.159", 
  "url": "http://httpbin.org/get"
}

注 意

在没有使用指定的请求头时,发送网络请求将使用Scrapy默认的请求头信息,示例代码如下:

#_*_coding:utf-8_*_
# 作者      :liuxiaowei
# 创建时间   :2/18/22 10:45 AM
# 文件      :设置请求头.py
# IDE      :PyCharm

import scrapy
import requests
class HeaderSpider(scrapy.Spider):
    # 定义爬虫名称
    name = 'header'

    def start_requests(self):
        return [scrapy.Request('http://httpbin.org/get',  callback=self.parse)]

    # 响应信息
    def parse(self, response):
        print(response.text)

# 导入CrawlProcess类
from scrapy.crawler import CrawlerProcess
# 导入获取项目设置信息
from scrapy.utils.project import get_project_settings

# 程序入口
if __name__ == "__main__":
  # 创建CrawlProcess类对象并传入项目设置信息参数
  process = CrawlerProcess(get_project_settings())
  # 设置需要启动的爬虫名称
  process.crawl('header')
  # 启动爬虫
  process.start()

程序运行结果如下:

{
   
  "args": {
   }, 
  "headers": {
   
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 
    "Accept-Encoding": "gzip, deflate", 
    "Accept-Language": "en", 
    "Host": "httpbin.org", 
    "User-Agent": "Scrapy/2.5.1 (+https://scrapy.org)",   # Scrapy默认的请求头
    "X-Amzn-Trace-Id": "Root=1-620f4a86-17d6962a689a9de34bdeabcc"
  }, 
  "origin": "122.143.185.159", 
  "url": "http://httpbin.org/get"
}

1.2 设置随机请求头
设置请求头是爬虫程序中必不可少的一项设置,大多数网站都会根据请求头内容制订一些反爬策略,在Scrapy框架中如果只是简单地设置一个请求头的话,可以在当前的爬虫文件中以参数的形式添加在网络请求当中。对于实现多个网络请求时,最好每发送一次请求就更换一个请求头,这样可以避免请求头的反爬策略。对于这样的需求可以使用自定义中间件的方式实现一个设置随机请求头的中间件。步骤如下:

1.2.1 在Pycharm命令行窗口通过执行"scrapy startproject header" 命令创建一个名为“header“的项目。如下图
image.png

1.2.2 然后通过“cd header“命令进入到项目的文件夹,然后通过“scrapy genspider headerSpider quotes.toscrape.com“ 命令创建名为“headerSpider“的爬虫文件。如下图:

image.png

1.2.3 打开headerSpider.py文件,配置测试网络请求的爬虫代码。代码如下:
# 导入scrapy框架
import scrapy
# 导入ssl模块,避免证书验证错误
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
class HeaderspiderSpider(scrapy.Spider):
    name = 'headerSpider'
    allowed_domains = ['quotes.toscrape.com']
    start_urls = ['http://quotes.toscrape.com/']
    def start_requests(self):

        # 设置爬取目标的地址,取前8页的网址
        for i in range(8):
            yield scrapy.Request(url=self.start_urls[0] + f'page/{i+1}/', callback=self.parse)

    def parse(self, response):
        # 打印每次网络请求的请求头信息
        print('请求信息:', response.request.headers.get('User-Agent'))
        pass

1.2.4 打开middlewares.py文件,在该文件中首先导入fake-useragent模块中的UserAgent类(如果没有安装fake-useragent模块,需要提前安装),然后创建RandomHeaderMiddleware类并通过init()函数进行类的初始化工作。代码如下:

from fake_useragent import UserAgent  # 导入请求头类
# 自定义随机请求头的中间件
class RandomHeaderMiddleware(object):
    def __init__(self, crawler):
        self.ua = UserAgent()  # 随机请求头对象
        # 如果配置文件中不存在就使用默认的Google Chrome请求头
        self.type = crawler.settings.get("RANDOM_UA_TYPE", "chrome")

1.2.5 重写from_crawler()方法,在该方法中将cls()实例对象返回,代码如下:

@classmethod
    def from_crawler(cls, crawler):
        # 返回cls()实例对象
        return cls(crawler)

1.2.6 重写process_request()方法,在该方法中实现设置随机生成的请求头信息。代码如下:

# 发送网络请求时调用该方法
def start_requests(self):
      # 设置爬取目标的地址,取前8页的网址
    for i in range(8):
        yield scrapy.Request(url=self.start_urls[0] + f'page/{i+1}/', callback=self.parse)

1.2.7 打开settings.py文件,在该文件中找到DOWNLOADER_MIDDLEWARES配置信息,然后配置自定义的请求头中间件,并把默认生成的下载中间件禁用,最后在配置信息的下面添加请求头类型。代码如下:

DOWNLOADER_MIDDLEWARES = {
   
    # 启动自定义随机请求头中间件
   'header.middlewares.RandomHeaderMiddleware':400,
    # 设为None,禁用默认创建的下载中间件
   'header.middlewares.HeaderDownloaderMiddleware': None,
}
# 配置请求头类型为随机,此处还可以设置为ie、firefox以及chrome
RANDOM_UA_TYPE = "random"

1.2.8 启动"headerSpider"爬虫,控制台将输出八次请求,并分别使用不同的请求头信息。如下所示:

2022-02-18 16:13:13 [scrapy.core.engine] DEBUG: Crawled (404) <GET http://quotes.toscrape.com/robots.txt> (referer: None)
2022-02-18 16:13:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/1/> (referer: None)
请求信息: b'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20130331 Firefox/21.0' 
2022-02-18 16:13:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/5/> (referer: None)
2022-02-18 16:13:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/3/> (referer: None)
2022-02-18 16:13:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/2/> (referer: None)
2022-02-18 16:13:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/4/> (referer: None)
2022-02-18 16:13:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/6/> (referer: None)
2022-02-18 16:13:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/8/> (referer: None)
2022-02-18 16:13:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/7/> (referer: None)
请求信息: b'Mozilla/5.0 (Windows NT 5.0; rv:21.0) Gecko/20100101 Firefox/21.0'
请求信息: b'Mozilla/5.0 (Windows NT 6.2; rv:22.0) Gecko/20130405 Firefox/22.0'
请求信息: b'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)'
请求信息: b'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1309.0 Safari/537.17'
请求信息: b'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36'
请求信息: b'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36 Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10'
请求信息: b'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36'
2022-02-18 16:13:13 [scrapy.core.engine] INFO: Closing spider (finished)

总 结

本次自定义中间件的重点是需要重写process_request()方法,该方法是Scrapy发送网络请求时所调用的,参数request表示当前的请求对象,例如请求头、请求方式以及请求地址等信息。参数spider表示爬虫程序。该方法返回值的具体说明如下:

  • None:最常见的返回值,表示该方法已经执行完成并向下执行爬虫程序
  • response: 停止该方法的执行,并开始执行process_response()方法
  • request: 停止当前的中间件,将当前的请求交个Scrapy引擎重新执行
  • IgnoreRequest:抛出异常对象,再通过process_exception() 方法处理异常,结束当前的网络请求
相关文章
|
15天前
|
数据采集 存储 JSON
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第27天】本文介绍了Python网络爬虫Scrapy框架的实战应用与技巧。首先讲解了如何创建Scrapy项目、定义爬虫、处理JSON响应、设置User-Agent和代理,以及存储爬取的数据。通过具体示例,帮助读者掌握Scrapy的核心功能和使用方法,提升数据采集效率。
59 6
|
1月前
|
数据采集 中间件 Python
Scrapy爬虫框架-通过Cookies模拟自动登录
Scrapy爬虫框架-通过Cookies模拟自动登录
|
16天前
|
数据采集 前端开发 中间件
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第26天】Python是一种强大的编程语言,在数据抓取和网络爬虫领域应用广泛。Scrapy作为高效灵活的爬虫框架,为开发者提供了强大的工具集。本文通过实战案例,详细解析Scrapy框架的应用与技巧,并附上示例代码。文章介绍了Scrapy的基本概念、创建项目、编写简单爬虫、高级特性和技巧等内容。
39 4
|
15天前
|
消息中间件 NoSQL Java
springboot整合常用中间件框架案例
该项目是Spring Boot集成整合案例,涵盖多种中间件的使用示例,每个案例项目使用最小依赖,便于直接应用到自己的项目中。包括MyBatis、Redis、MongoDB、MQ、ES等的整合示例。
65 1
|
15天前
|
数据采集 中间件 API
在Scrapy爬虫中应用Crawlera进行反爬虫策略
在Scrapy爬虫中应用Crawlera进行反爬虫策略
|
1月前
|
消息中间件 数据采集 数据库
小说爬虫-03 爬取章节的详细内容并保存 将章节URL推送至RabbitMQ Scrapy消费MQ 对数据进行爬取后写入SQLite
小说爬虫-03 爬取章节的详细内容并保存 将章节URL推送至RabbitMQ Scrapy消费MQ 对数据进行爬取后写入SQLite
24 1
|
1月前
|
消息中间件 数据采集 数据库
小说爬虫-02 爬取小说详细内容和章节列表 推送至RabbitMQ 消费ACK确认 Scrapy爬取 SQLite
小说爬虫-02 爬取小说详细内容和章节列表 推送至RabbitMQ 消费ACK确认 Scrapy爬取 SQLite
18 1
|
1月前
|
数据采集 SQL 数据库
小说爬虫-01爬取总排行榜 分页翻页 Scrapy SQLite SQL 简单上手!
小说爬虫-01爬取总排行榜 分页翻页 Scrapy SQLite SQL 简单上手!
81 0
|
6月前
|
数据采集 中间件 Python
Scrapy爬虫:利用代理服务器爬取热门网站数据
Scrapy爬虫:利用代理服务器爬取热门网站数据
|
1月前
|
数据采集 中间件 数据挖掘
Scrapy 爬虫框架(一)
Scrapy 爬虫框架(一)