2.8 Requests 和 Responses Scrapy 核心组件详解:Requests 和 Responses 在 Scrapy 爬虫框架中,Requests 和 Responses 是数据交互的基石。Request 对象代表爬虫向网站发起的请求,而 Response 对象则代表网站返回的响应。理解它们的工作原理和使用方法对于构建高效、稳定的爬虫至关重要。 Request 对象 Request 对象封装了爬虫向服务器发送请求所需的所有信息。它包含了请求的 URL、请求方法(GET, POST 等)、请求头、请求体以及其他一些元数据。 1.1 Request 对象的基本属性 : 请求的 URL 地址,字符串类型。这是 Request 对象最核心的属性,指定了爬虫要访问的资源。
在 Scrapy 爬虫框架中,Requests 和 Responses 是数据交互的基石。Request 对象代表爬虫向网站发起的请求,而 Response 对象则代表网站返回的响应。理解它们的工作原理和使用方法对于构建高效、稳定的爬虫至关重要。
Request 对象封装了爬虫向服务器发送请求所需的所有信息。它包含了请求的 URL、请求方法(GET, POST 等)、请求头、请求体以及其他一些元数据。
1.1 Request 对象的基本属性
url: 请求的 URL 地址,字符串类型。这是 Request 对象最核心的属性,指定了爬虫要访问的资源。
method: 请求方法,字符串类型,默认为 'GET'。常用的方法包括 'GET'、'POST'、'PUT'、'DELETE' 等。
headers: 请求头,字典类型。用于设置 HTTP 请求头,例如 User-Agent、Cookie、Referer 等。
body: 请求体,字节类型。通常用于 POST 请求,包含要发送给服务器的数据。
cookies: 请求的 cookies,字典或列表类型。
meta: 元数据字典,用于在不同的回调函数之间传递数据。
callback: 回调函数,用于处理服务器返回的 Response 对象。
errback: 错误回调函数,用于处理请求过程中发生的错误。
dont_filter: 布尔值,默认为 False。如果设置为 True,则 Scrapy 的去重过滤器将不会过滤该请求。
priority: 请求的优先级,整数类型,默认为 0。优先级高的请求会优先被调度。
encoding: 请求的编码,字符串类型,默认为 'utf-8'。
1.2 创建 Request 对象
可以使用 scrapy.Request 类来创建 Request 对象。
import scrapy class MySpider(scrapy.Spider): name = 'my_spider' start_urls = ['http://example.com'] def parse(self, response): # 创建一个新的 Request 对象 yield scrapy.Request( url='http://example.com/page2', callback=self.parse_page2, method='GET', headers={'User-Agent': 'My Spider'}, meta={'item_id': 123} ) def parse_page2(self, response): # 从 meta 中获取数据 item_id = response.meta['item_id'] print(f"Processing item with ID: {item_id}") # 处理响应 pass
1.3 Request 对象的使用场景
翻页抓取: 通过创建新的 Request 对象,可以抓取网站上的多个页面。
POST 请求: 可以发送 POST 请求,例如提交表单数据。
模拟登录: 通过设置 Cookie 和请求头,可以模拟用户的登录行为。
传递数据: 使用 meta 属性可以在不同的回调函数之间传递数据。
1.4 Request 对象的优先级
Request 对象的 priority 属性可以控制请求的优先级。优先级高的请求会优先被调度器处理。这在需要优先抓取某些重要页面时非常有用。
import scrapy class PrioritySpider(scrapy.Spider): name = 'priority_spider' start_urls = ['http://example.com'] def parse(self, response): # 创建一个高优先级的请求 yield scrapy.Request( url='http://example.com/important_page', callback=self.parse_important, priority=10 ) # 创建一个默认优先级的请求 yield scrapy.Request( url='http://example.com/normal_page', callback=self.parse_normal ) def parse_important(self, response): print("Processing important page") pass def parse_normal(self, response): print("Processing normal page") pass
1.5 Request 对象的去重
Scrapy 默认会对 Request 对象进行去重,防止重复抓取同一个 URL。可以通过设置 dont_filter=True 来禁用去重功能。
import scrapy class NoFilterSpider(scrapy.Spider): name = 'no_filter_spider' start_urls = ['http://example.com'] def parse(self, response): # 创建一个不进行去重的请求 yield scrapy.Request( url='http://example.com/page', callback=self.parse_page, dont_filter=True ) def parse_page(self, response): print("Processing page") pass
1.6 Request 对象错误处理
可以使用 errback 属性来指定错误回调函数,用于处理请求过程中发生的错误。
import scrapy class ErrorHandlingSpider(scrapy.Spider): name = 'error_handling_spider' start_urls = ['http://example.com'] def parse(self, response): # 创建一个可能出错的请求 yield scrapy.Request( url='http://example.com/nonexistent_page', callback=self.parse_page, errback=self.handle_error ) def parse_page(self, response): print("Processing page") pass def handle_error(self, failure): # 处理错误 print(f"Error occurred: {failure}")
Response 对象封装了服务器返回的响应信息。它包含了响应的状态码、响应头、响应体以及其他一些元数据。
2.1 Response 对象的基本属性
url: 响应的 URL 地址,字符串类型。
status: 响应状态码,整数类型。例如 200 表示成功,404 表示未找到。
headers: 响应头,字典类型。
body: 响应体,字节类型。包含了服务器返回的内容。
text: 响应体,字符串类型。是 body 的解码后的结果,默认使用 UTF-8 编码。
encoding: 响应的编码,字符串类型。
request: 生成该 Response 对象的 Request 对象。
meta: 从 Request 对象传递过来的元数据字典。
2.2 Response 对象的类型
Scrapy 提供了多种 Response 对象类型,用于处理不同类型的响应。
scrapy.http.Response: 通用的 Response 对象,用于处理 HTML、XML 等文本类型的响应。
scrapy.http.HtmlResponse: 专门用于处理 HTML 响应的对象。它提供了方便的 CSS 和 XPath 选择器。
scrapy.http.XmlResponse: 专门用于处理 XML 响应的对象。它提供了 XPath 选择器。
scrapy.http.TextResponse: 专门用于处理文本响应的对象。
scrapy.http.JsonResponse: 专门用于处理 JSON 响应的对象。 可以直接将response.text 解析成json对象。
2.3 Response 对象的使用
在爬虫的回调函数中,可以访问 Response 对象,并从中提取数据。
import scrapy class MySpider(scrapy.Spider): name = 'my_spider' start_urls = ['http://example.com'] def parse(self, response): # 获取响应状态码 status_code = response.status print(f"Status code: {status_code}") # 获取响应头 headers = response.headers print(f"Headers: {headers}") # 获取响应体 body = response.body print(f"Body: {body[:100]}...") # 打印前 100 个字节 # 获取响应文本 text = response.text print(f"Text: {text[:100]}...") # 打印前 100 个字符 # 使用 CSS 选择器提取数据 title = response.css('title::text').get() print(f"Title: {title}") # 使用 XPath 选择器提取数据 description = response.xpath('//meta[@name="description"]/@content').get() print(f"Description: {description}") # 从 meta 中获取数据 item_id = response.request.meta.get('item_id') if item_id: print(f"Item ID from meta: {item_id}")
2.4 HtmlResponse 对象的 CSS 和 XPath 选择器
HtmlResponse 对象提供了方便的 CSS 和 XPath 选择器,用于从 HTML 文档中提取数据。
CSS 选择器: 使用 CSS 语法来选择 HTML 元素。
XPath 选择器: 使用 XPath 语法来选择 XML 文档中的节点。
import scrapy class SelectorSpider(scrapy.Spider): name = 'selector_spider' start_urls = ['http://example.com'] def parse(self, response): # 使用 CSS 选择器提取标题 title = response.css('title::text').get() print(f"Title: {title}") # 使用 XPath 选择器提取描述 description = response.xpath('//meta[@name="description"]/@content').get() print(f"Description: {description}") # 使用 CSS 选择器提取所有链接 links = response.css('a::attr(href)').getall() print(f"Links: {links}") # 使用 XPath 选择器提取所有段落文本 paragraphs = response.xpath('//p/text()').getall() print(f"Paragraphs: {paragraphs}")
2.5 Response 对象的编码
Response 对象的 encoding 属性表示响应的编码。Scrapy 会自动检测响应的编码,并将其设置为 encoding 属性。可以使用 response.text 属性来获取解码后的响应文本。
如果 Scrapy 无法正确检测响应的编码,可以手动设置 encoding 属性。
import scrapy class EncodingSpider(scrapy.Spider): name = 'encoding_spider' start_urls = ['http://example.com'] def parse(self, response): # 尝试手动设置编码 response.encoding = 'gbk' text = response.text print(f"Text: {text[:100]}...")
以下 Mermaid 流程图展示了 Request 和 Response 在 Scrapy 中的交互流程:
流程说明:
Spider: 爬虫定义了如何抓取网站。它创建 Request 对象,并指定回调函数来处理 Response 对象。
Scheduler: 调度器接收来自爬虫的 Request 对象,并将其放入队列中等待下载。
Downloader: 下载器从调度器中取出 Request 对象,并向服务器发送请求。
Downloader Middleware: 下载器中间件可以拦截和修改 Request 对象和 Response 对象。
Web Server: Web 服务器接收来自下载器的请求,并返回响应。
Response: 响应对象包含了服务器返回的响应信息。
Spider: 爬虫接收到 Response 对象,并调用回调函数来处理响应。
Item Pipeline: 项目管道负责处理从响应中提取的数据。
Storage: 存储器将处理后的数据存储到数据库、文件或其他存储介质中。
Requests 和 Responses 是 Scrapy 爬虫框架的核心组件。理解它们的工作原理和使用方法对于构建高效、稳定的爬虫至关重要。通过灵活地使用 Request 对象的各种属性,可以实现各种复杂的抓取需求。通过分析 Response 对象,可以提取出所需的数据,并将其存储到数据库或其他存储介质中。 掌握 Request 和 Response 的使用,是成为一名优秀的 Scrapy 爬虫工程师的必备技能。