程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Python 基础

  • Python 进阶

  • Python爬虫

  • Scrapy 爬虫框架

    • Scrapy 框架核心:深入理解其工作流程
    • Scrapy 入门实战:从零到一构建你的第一个爬虫
    • Scrapy核心对象:Response超详细指南
      • 一、Response 对象的核心属性
        • 处理 JSON 数据
      • 二、与请求 (Request) 相关的属性
      • 三、内置选择器 (Selectors)
        • 3.1 Selector 和 SelectorList
        • 3.2 高级选择器技巧
        • 3.3 提取数据:get() vs extract()
      • 四、便捷的请求创建 (response.follow)
      • 五、博客列表页抓取文章
      • 六、网站的编码判断错误处理
      • 七、总结
    • Scrapy 核心配置与调试技巧
    • Scrapy Items与Pipeline数据管道
    • Scrapy 图片与文件下载
    • Scrapy 模拟登录与Cookie处理
    • Scrapy CrawlSpider全站爬取
    • Scrapy 中间件:请求与响应的强大控制器
    • Scrapy-Redis:从单机到分布式集群
  • Python
  • Scrapy 爬虫框架
scholar
2025-07-22
目录

Scrapy核心对象:Response超详细指南

# Scrapy 核心对象:Response 超详细指南

在 Scrapy 的工作流中,当下载器完成页面下载后,会将获取到的内容封装成一个 Response 对象,并发送给 Spider 进行解析。这个 Response 对象是我们进行数据提取和发起后续请求的全部依据,因此,深入理解它的属性和方法至关重要。

学习建议:本文档是 Response 对象的详细参考手册。如果你是 Scrapy 的初学者,建议先完成我们的 Scrapy 入门实战教程,对 Scrapy 的项目流程有了基本概念后,再来深入阅读本文,效果会更佳。

# 一、Response 对象的核心属性

这些属性提供了关于响应本身最基本、最重要的信息。

属性 类型 描述
response.url str 当前响应的最终 URL 地址。如果途中发生过重定向,这里会是重定向后的地址。
response.status int HTTP 响应状态码。例如 200 (成功), 404 (未找到), 302 (重定向)。
response.headers dict 服务器返回的响应头。这是一个类字典对象,包含了 Content-Type, Content-Length, Set-Cookie 等信息。
response.body bytes 原始的响应体,是未经任何解码的字节 (bytes) 类型。当你需要处理图片、视频等二进制文件时,必须使用此属性。
response.text str 解码后的响应体,是字符串 (str) 类型。Scrapy 会根据响应头的 Content-Type 自动选择编码格式进行解码。当你处理 HTML、JSON、XML 等文本内容时,通常使用此属性。
response.encoding str Scrapy 推断出的响应编码格式,response.text 就是基于这个编码来解码 response.body 的。

# 处理 JSON 数据

如果响应内容是 JSON 格式,可以直接使用 .json() 方法将其解析为 Python 的字典或列表。

  • response.json(): 将 JSON 响应体反序列化为 Python 对象。如果响应体不是有效的 JSON,会引发错误。
# 假设 response 的内容是 '{"name": "Scrapy", "version": "2.5"}'
data = response.json()
print(data['name'])  # 输出: Scrapy
1
2
3

# 二、与请求 (Request) 相关的属性

Response 对象还保留了当初引发它的那个 Request 对象的信息,方便我们追溯和传递数据。

属性 类型 描述
response.request Request 对象 产生此响应的那个 Request 对象实例。
response.request.url str 原始请求的 URL 地址,不会包含重定向后的地址。
response.request.headers dict 发送请求时所使用的请求头。
response.request.meta dict 一个非常重要的属性!它是 Request 的元数据字典,用于在不同的请求处理函数之间传递数据。你在发起请求时附加的 meta 信息,可以在接收响应时通过此属性取回。

# 三、内置选择器 (Selectors)

Scrapy 的 Response 对象最强大的地方在于它内置了功能强大的选择器,无需再引入 BeautifulSoup 等第三方库。

  • response.xpath(...): 使用 XPath 语法进行选择。
  • response.css(...): 使用 CSS 语法进行选择。

# 3.1 Selector 和 SelectorList

当你调用 response.xpath() 或 response.css() 时,你得到的并不是直接的数据,而是:

  • Selector 对象:如果你的选择器只匹配到一个结果。
  • SelectorList 对象:如果匹配到多个结果,它表现得像一个 Python 列表,里面包含了多个 Selector 对象。

选择器可以链式调用:你可以对一个 Selector 或 SelectorList 对象再次调用 .xpath() 或 .css() 方法,这表示从当前已选中的节点下进行相对查找,非常有用。

# 3.2 高级选择器技巧

除了基本的标签和类选择,你还可以使用更高级的技巧来精确定位。

XPath 示例:

  • //a/@href: 选取所有 <a> 标签的 href 属性值。
  • //p/text(): 选取所有 <p> 标签下的直接文本节点。
  • //div[contains(@class, "info")]: 选取 class 属性包含 "info" 字符串的 <div> 标签。
  • //button[contains(text(), "下一页")]: 选取文本内容包含 "下一页" 的 <button> 标签。

CSS 示例:

  • a::attr(href): (Scrapy 特有)选取所有 <a> 标签的 href 属性值。
  • p::text: 选取所有 <p> 标签下的文本内容。
  • div[class*="info"]: 选取 class 属性包含 "info" 字符串的 <div> 标签。
  • a:nth-child(2): 选取作为其父元素的第二个子元素的 <a> 标签。

# 3.3 提取数据:get() vs extract()

要从 Selector 或 SelectorList 中提取出最终的文本或属性数据,你需要调用提取方法。Scrapy 提供了两套API,新版推荐使用 get()/getall()。

新版 API (推荐) 旧版 API (兼容) 描述
.get() .extract_first() 从选择器结果中提取第一个匹配项。如果结果为空,返回 None。这是最安全、最常用的方法。
.getall() .extract() 提取所有匹配项,返回一个列表。如果结果为空,返回一个空列表 []。

# 四、便捷的请求创建 (response.follow)

response.follow() 是一个用于创建后续请求的快捷方法,它比手动创建 scrapy.Request 对象更智能。

  • response.follow(url, callback, meta, ...):
    • 它能自动处理相对 URL。例如 url="page2.html" 会被自动转换成 http://example.com/page2.html。
    • 它能处理 Selector 对象。你可以直接传入一个指向 <a> 标签的 Selector,它会自动提取 href 属性来创建请求。
# 手动方式
next_page_url = response.css('a.next::attr(href)').get()
if next_page_url:
    # 需要手动拼接完整 URL
    absolute_url = response.urljoin(next_page_url)
    yield scrapy.Request(absolute_url, callback=self.parse)

# 使用 response.follow() 的便捷方式
next_page_selector = response.css('a.next')
if next_page_selector:
    # 直接传入 selector,自动处理
    yield response.follow(next_page_selector, callback=self.parse)
1
2
3
4
5
6
7
8
9
10
11
12

# 五、博客列表页抓取文章

下面的代码演示了如何从一个博客列表页抓取文章,然后通过 meta 传递文章标题到详情页,并使用 response.follow 进行翻页。

import scrapy

class ResponseDemoSpider(scrapy.Spider):
    name = 'response_demo'
    start_urls = ['http://duanzixing.com/']

    def parse(self, response, **kwargs):
        print(f"\n>>>>>> 正在解析列表页: {response.url}")

        # 使用链式调用和高级选择器
        for article in response.css('article.excerpt'):
            title = article.css('h2 a::text').get()
            detail_url = article.css('h2 a::attr(href)').get()

            if title and detail_url:
                # 使用 meta 将标题传递给下一个解析函数
                yield response.follow(
                    detail_url,
                    callback=self.parse_detail,
                    meta={'article_title': title.strip()}
                )
        
        # --- 处理分页 ---
        # 寻找文本为 "下一页" 的链接
        next_page_link = response.xpath('//a[contains(text(), "下一页")]')
        if next_page_link:
            yield response.follow(next_page_link, callback=self.parse)

    def parse_detail(self, response):
        # 通过 response.request.meta 获取传递过来的数据
        title = response.request.meta.get('article_title', '未知标题')

        print(f"\n------ 正在解析详情页: {response.url}")
        print(f"------ 从 meta 中获取到的标题: {title}")
        
        # 提取详情页的内容
        content_paragraphs = response.css('article.article-content p::text').getall()
        content = "\n".join(p.strip() for p in content_paragraphs if p.strip())
        
        yield {
            'title': title,
            'url': response.url,
            'content': content,
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

# 六、网站的编码判断错误处理

偶尔,Scrapy 可能会错误地判断网站的编码,导致 response.text 出现乱码。此时,你可以:

  1. 查看 response.encoding,确认 Scrapy 推断的编码是否正确。
  2. 手动解码 response.body: correct_text = response.body.decode('gbk')
  3. 覆盖编码并重新生成响应: new_response = response.replace(encoding='gbk'),然后就可以正常使用 new_response.text。

# 七、总结

  1. 数据类型要分清: response.body 是 bytes(二进制),response.text 是 str(文本)。处理 JSON 用 response.json()。
  2. meta 是数据传递的桥梁: 使用 request.meta 可以在请求链中携带信息。
  3. follow 是翻页利器: 优先使用 response.follow() 创建后续请求,代码更简洁。
  4. 选择器返回的是 Selector 对象: 必须调用 .get() 或 .getall() 才能提取最终数据。
  5. 优先使用 get(): 提取单个数据时,.get() 比 .getall()[0] 更安全。
  6. allowed_domains 的作用域: 它限制的是 Spider 生成的后续请求,不限制 start_urls。
  7. 启动位置: 永远在项目的根目录下(包含 scrapy.cfg 的目录)执行 scrapy crawl。
编辑此页 (opens new window)
上次更新: 2025/07/27, 04:30:11
Scrapy 入门实战:从零到一构建你的第一个爬虫
Scrapy 核心配置与调试技巧

← Scrapy 入门实战:从零到一构建你的第一个爬虫 Scrapy 核心配置与调试技巧→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式