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() 方法处理异常,结束当前的网络请求
相关文章
|
2天前
|
数据采集 中间件 Python
Scrapy爬虫框架-通过Cookies模拟自动登录
Scrapy爬虫框架-通过Cookies模拟自动登录
|
2天前
|
数据采集 中间件 数据挖掘
Scrapy 爬虫框架(一)
Scrapy 爬虫框架(一)
|
2天前
|
数据采集 XML 前端开发
Scrapy 爬虫框架(二)
Scrapy 爬虫框架(二)
|
2月前
|
数据采集 中间件 调度
Scrapy 爬虫框架的基本使用
Scrapy 爬虫框架的基本使用
|
2月前
|
机器学习/深度学习 数据采集 数据可视化
基于爬虫和机器学习的招聘数据分析与可视化系统,python django框架,前端bootstrap,机器学习有八种带有可视化大屏和后台
本文介绍了一个基于Python Django框架和Bootstrap前端技术,集成了机器学习算法和数据可视化的招聘数据分析与可视化系统,该系统通过爬虫技术获取职位信息,并使用多种机器学习模型进行薪资预测、职位匹配和趋势分析,提供了一个直观的可视化大屏和后台管理系统,以优化招聘策略并提升决策质量。
117 4
|
2月前
|
数据采集 存储 搜索推荐
打造个性化网页爬虫:从零开始的Python教程
【8月更文挑战第31天】在数字信息的海洋中,网页爬虫是一艘能够自动搜集网络数据的神奇船只。本文将引导你启航,用Python语言建造属于你自己的网页爬虫。我们将一起探索如何从无到有,一步步构建一个能够抓取、解析并存储网页数据的基础爬虫。文章不仅分享代码,更带你理解背后的逻辑,让你能在遇到问题时自行找到解决方案。无论你是编程新手还是有一定基础的开发者,这篇文章都会为你打开一扇通往数据世界的新窗。
|
3月前
|
数据采集 存储 JSON
从零到一构建网络爬虫帝国:HTTP协议+Python requests库深度解析
【7月更文挑战第31天】在网络数据的海洋中,使用Python的`requests`库构建网络爬虫就像探索未知的航船。HTTP协议指导爬虫与服务器交流,收集信息。HTTP请求包括请求行、头和体,响应则含状态行、头和体。`requests`简化了发送各种HTTP请求的过程。
74 4
|
6天前
|
数据采集 存储 数据挖掘
深入探索 Python 爬虫:高级技术与实战应用
本文介绍了Python爬虫的高级技术,涵盖并发处理、反爬虫策略(如验证码识别与模拟登录)及数据存储与处理方法。通过asyncio库实现异步爬虫,提升效率;利用tesseract和requests库应对反爬措施;借助SQLAlchemy和pandas进行数据存储与分析。实战部分展示了如何爬取电商网站的商品信息及新闻网站的文章内容。提醒读者在实际应用中需遵守法律法规。
121 66
|
3月前
|
数据采集 存储 API
在信息时代,Python爬虫用于自动化网络数据采集,提高效率。
【7月更文挑战第5天】在信息时代,Python爬虫用于自动化网络数据采集,提高效率。基本概念包括发送HTTP请求、解析HTML、存储数据及异常处理。常用库有requests(发送请求)和BeautifulSoup(解析HTML)。基本流程:导入库,发送GET请求,解析网页提取数据,存储结果,并处理异常。应用案例涉及抓取新闻、商品信息等。
85 2
|
23天前
|
数据采集 存储 JSON
从零到一构建网络爬虫帝国:HTTP协议+Python requests库深度解析
在网络数据的海洋中,网络爬虫遵循HTTP协议,穿梭于互联网各处,收集宝贵信息。本文将从零开始,使用Python的requests库,深入解析HTTP协议,助你构建自己的网络爬虫帝国。首先介绍HTTP协议基础,包括请求与响应结构;然后详细介绍requests库的安装与使用,演示如何发送GET和POST请求并处理响应;最后概述爬虫构建流程及挑战,帮助你逐步掌握核心技术,畅游数据海洋。
52 3