当前位置: 首页 > news >正文

Scrapy 中间件

Scrapy 中间件的作用

中间件(Middleware)是一种可以介入到Scrapy的请求(request)-响应(response)处理过程中的钩子机制,允许开发者在执行特定任务时对请求或响应进行自定义处理。中间件可以看作是位于Scrapy引擎和爬虫、下载器之间的一个处理层,用于修改或扩展Scrapy的默认行为。

Scrapy 中间件的分类

1. 下载器中间件(Downloader Middleware)

下载器中间件用于处理发出的请求和下载的响应,它们在请求到达下载器之前或响应到达引擎之前执行。这类中间件可以用于:

  • 修改请求头(比如User-Agent、Cookies等)
  • 设置代理(如IP代理)
  • 处理重定向
  • 管理请求失败的重试机制
  • 捕获和处理下载过程中发生的异常

2. 爬虫中间件(Spider Middleware)

爬虫中间件用于处理爬虫生成的请求以及接收到的响应。在引擎把响应交给爬虫处理之前,或者爬虫生成的请求交给引擎之前,爬虫中间件都有机会对这些对象进行处理。具体应用场景包括:

  • 对爬虫产生的请求进行过滤或修改
  • 处理从下载器返回的响应,比如进行一些前置的数据清理
  • 修改从爬虫传出的项目(item)

下载器中间件方法

/*** 处理每一个经过下载器的请求** @param request 待处理的请求对象(scrapy.http.Request)* @param spider  当前正在运行的爬虫实例* @return * --------------- 可以返回 None,表示继续处理这个请求。* --------------- 可以返回 scrapy.http.Response,则中间件会返回这个响应对象并跳过下载过程,直接把响应传递给爬虫。* --------------- 可以返回 scrapy.exceptions.IgnoreRequest 异常,则请求会被丢弃,触发 spider 的 request_dropped 信号。*/
process_request(self, request, spider)
/*** 处理下载器返回的响应* * @param request  产生这个响应的请求对象(scrapy.http.Request)* @param response 当前的响应对象(scrapy.http.Response)* @param spider   当前的爬虫实例* @return * --------------- 可以返回 response 对象(或者修改后的新 response 对象),继续交给下一个中间件处理或直接给爬虫。* --------------- 可以返回一个新的 scrapy.http.Request,该请求会重新被调度和下载。* --------------- 可以抛出 scrapy.exceptions.IgnoreRequest 异常,表示忽略此请求。*/
process_response(self, request, response, spider)
/*** 当下载器或者 process_request/process_response 方法抛出异常时,调用此方法处理异** @param request   产生这个响应的请求对象(scrapy.http.Request)* @param exception 抛出的异常对象* @param spider    当前的爬虫实例* @return * --------------- 可以返回 None,继续交由其他中间件处理。* --------------- 可以返回一个 scrapy.http.Response 对象,表示已经处理了该异常并提供了替代的响应。* --------------- 可以返回一个 scrapy.http.Request 对象,以重新调度此请求。*/
process_exception(self, request, exception, spider)

爬虫中间件方法

/*** 当下载器将响应传递给爬虫之前,调用此方法处理响应** @param response 下载器返回的响应对象* @param spider   当前的爬虫实例* @return * --------------- 如果返回 None,响应将继续传递给爬虫处理。* --------------- 可以抛出 scrapy.exceptions.IgnoreRequest,表示忽略此请求和响应,不会传递给爬虫。*/
process_spider_input(self, response, spider)
/*** 处理爬虫返回的结果(通常是 item 或新的 request)** @param response 传递给爬虫的响应对象* @param result   爬虫返回的结果,通常是生成器或列表,包含 Item 对象、Request 对象等* @param spider   当前的爬虫实例* @return 必须返回一个可迭代对象,包含 Item 对象或 Request 对象。如果需要,可以对结果进行过滤或修改。*/
process_spider_output(self, response, result, spider)
/*** 当爬虫在处理响应过程中抛出异常时,调用此方法处理异常** @param response  导致异常的响应对象* @param exception 抛出的异常对象* @param spider    当前的爬虫实例* @return * --------------- 如果返回 None,Scrapy将继续处理该异常。* --------------- 如果返回一个可迭代对象,将替代爬虫返回的结果。*/
process_spider_exception(self, response, exception, spider)
/*** 处理爬虫开始时生成的初始请求** @param start_requests 爬虫开始时生成的初始请求(可迭代对象)* @param spider         当前的爬虫实例* @return 必须返回一个可迭代对象,包含 Request 对象。*/
process_start_requests(self, start_requests, spider)

功能实现

实现随机 User-Agent

1. 在 Scrapy 项目的 middlewares.py 文件中自定义一个下载器中间件类,在这个中间件中,process_request 方法会为每个请求随机选择一个 User-Agent。

import randomclass RandomUserAgentMiddleware:def __init__(self, user_agents):self.user_agents = user_agents@classmethoddef from_crawler(cls, crawler):return cls(# 获取 settings.py 中的配置user_agents=crawler.settings.get('USER_AGENTS'))def process_request(self, request, spider):# 从集合中随机取一个元素user_agent = random.choice(self.user_agents)if user_agent:request.headers['User-Agent'] = user_agent

2. 在 Scrapy 项目的 settings.py 文件中配置中间件,并提供一个 User-Agent 列表。

# 配置多个 USER_AGENT
USER_AGENTS = ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 SLBrowser/9.0.3.5211 SLBChan/25","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/57.0 Safari/537.3"
]# 开启下载器中间件
DOWNLOADER_MIDDLEWARES = {"myproject.middlewares.RandomUserAgentMiddleware": 543,
}# 关闭 robots.txt 检查
ROBOTSTXT_OBEY = False

3. 验证是否成功

import scrapyclass BaiduSpider(scrapy.Spider):name = "baidu"allowed_domains = ["www.baidu.com"]start_urls = ["https://www.baidu.com"]def parse(self, response):print("随机 User-Agent:", response.request.headers['User-Agent'])

实现随机 IP 代理

1. 在 Scrapy 项目的 middlewares.py 文件中自定义一个下载器中间件类。

import random
import base64class RandomProxyMiddleware:def __init__(self, proxies):self.proxies = proxies@classmethoddef from_crawler(cls, crawler):# 从 settings.py 中获取 PROXIES 列表return cls(proxies=crawler.settings.get('PROXIES'))def process_request(self, request, spider):# 随机选择一个代理proxy = random.choice(self.proxies)if '@' in proxy:# 配置带账号密码的credentials, proxy_url = proxy.split('@')proto, credentials = credentials.split('//')proto = proto + "//"auth = base64.b64encode(credentials.encode('utf-8')).decode('utf-8')request.headers['Proxy-Authorization'] = 'Basic ' + authrequest.meta['proxy'] = proto + proxy_urlelse:# 配置无账号密码的request.meta['proxy'] = proxy

2. 在 Scrapy 项目的 settings.py 文件中配置中间件,并提供一个代理列表。

# 定义代理列表,代理太多可以存在数据库中
PROXIES = [# 无密码的写法'http://122.116.xxx.xxx:8888',# 带账号密码的写法,代理ip需要在服务商处进行购买'http://user:pass@14.29.xxx.xxx:16817',
]# 开启下载器中间件
DOWNLOADER_MIDDLEWARES = {"myproject.middlewares.RandomProxyMiddleware": 543,
}# 关闭 robots.txt 检查
ROBOTSTXT_OBEY = False

实现 selenium 动态数据加载渲染完成后再爬取数据

1. 在 Scrapy 项目的 middlewares.py 文件中自定义一个下载器中间件类。

from selenium import webdriver
import time
from scrapy.http import HtmlResponseclass SeleniumMiddleware:def __init__(self):# 打开一个无头模式的谷歌浏览器# options = webdriver.ChromeOptions()# options.add_argument('--headless')# options.add_argument('--disable-gpu')  # 如果你使用的是 Windows 系统,需要加上这行# driver = webdriver.Chrome(options=options)# 打开一个 谷歌浏览器self.driver = webdriver.Chrome()def process_request(self, request, spider):url = request.url# 比如 http://abc.com/123?day=111 这个url中的数据要加载很久才能渲染完成显示出来,这时就需要对这个url使用 selenium 动态加载if 'day' in url:  # 判断url中包含的字符串,用于找到这个url地址# 打开urlself.driver.get(url)# 等待渲染完成时间time.sleep(5)# 拿到渲染完成后的页面数据data = self.driver.page_source# 关闭浏览器self.driver.close()# 封装新的response对象返回给爬虫,让爬虫从data中爬取数据response = HtmlResponse(url=url, body=data, encoding='utf-8', request=request)return response

2. 在 Scrapy 项目的 settings.py 文件中配置中间件。

# 开启下载器中间件
DOWNLOADER_MIDDLEWARES = {"myproject.middlewares.SeleniumMiddleware": 543,
}# 关闭 robots.txt 检查
ROBOTSTXT_OBEY = False


http://www.mrgr.cn/news/1017.html

相关文章:

  • 揭秘组合模式:设计更智能、更灵活的软件架构
  • tortoisegit下载及其使用流程
  • 第二届机器人与软件工程前沿国际会议在贵阳闭幕
  • 数据结构与算法 - 双指针
  • Linux 网络套接字解析:实现网络通信
  • 响应式Web设计:纯HTML和CSS的实现技巧
  • 萝卜快跑和端到端的自动驾驶(1)
  • 支持redis和zookeeper的分布式锁组件lock4j
  • MyBatis首篇-入门第一文
  • scikit-learn特征预处理
  • SOCKS5代理UDP转发:探秘网络世界的隐形传送带
  • Scala 闭包
  • 超高速NVME FPGA存储卡记录
  • Maven的使用
  • XSS Game
  • UE5 日期时间蓝图变量 加减节点
  • 本地生活服务平台源码在哪里?2大获取渠道源码质量解析!
  • Android架构组件中的MVVM
  • ubuntu 安装两个nginx实例时的坑,非默认nginx实例配置修改总也不生效的问题
  • sentinel集成springcloud实现限流熔断