You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Scrapy的TextResponse、HtmlResponse及XmlResponse?附示例调整

Scrapy 用 HtmlResponse 的问题解答

1. Scrapy 什么时候会返回 HtmlResponse?

其实不用额外设置——Scrapy 会自动根据响应的 Content-Type 判断返回的响应类型:如果目标页面是 HTML(响应头里 Content-Type 是 text/html),Scrapy 就会直接返回 HtmlResponse,只有非 HTML 内容(比如 JSON、纯文本)才会返回其他响应类型。

2. 要不要写 def parse(self, response: HtmlResponse):?

这是类型注解,不是强制要求,但写了有好处:

  • 它不会改变 Scrapy 实际返回的响应类型,只是告诉 IDE 和其他开发者,这个 parse 方法接收的是 HtmlResponse 实例
  • 加上注解后,IDE 会自动提示 HtmlResponse 的专属方法(比如 xpath()、css()),写代码更顺手

3. 修改教程示例代码(明确用 HtmlResponse)

原教程代码本来就在用 HtmlResponse(因为目标页面是 HTML),我们可以加上类型注解,或者加个验证逻辑,修改后的代码如下:

import scrapy
from scrapy.http import HtmlResponse  # 导入用于类型注解

class QuotesSpider(scrapy.Spider):
    name = "quotes"

    def start_requests(self):
        urls = [
            'https://quotes.toscrape.com/page/1/',
            'https://quotes.toscrape.com/page/2/',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    # 加上 HtmlResponse 类型注解,明确参数类型
    def parse(self, response: HtmlResponse):
        # 可选:验证响应类型,调试时用
        assert isinstance(response, HtmlResponse), "这不是 HtmlResponse 类型的响应"
        
        page = response.url.split("/")[-2]
        filename = f'quotes-{page}.html'
        with open(filename, 'wb') as f:
            f.write(response.body)
        self.log(f'Saved file {filename}')
        
        # 补充演示:用 HtmlResponse 的 css 方法提取数据
        for quote in response.css('div.quote'):
            yield {
                'text': quote.css('span.text::text').get(),
                'author': quote.css('small.author::text').get(),
                'tags': quote.css('div.tags a.tag::text').getall(),
            }

4. 特殊情况:强制转成 HtmlResponse

如果遇到网站返回的 Content-Type 标错了(比如明明是 HTML 却标成 text/plain),导致 Scrapy 返回 TextResponse,这时候可以写个下载中间件强制转换:

# 在项目的 middlewares.py 里加这个中间件
class ForceHtmlResponseMiddleware:
    def process_response(self, request, response, spider):
        # 判断是不是 TextResponse 但不是 HtmlResponse
        if isinstance(response, scrapy.http.TextResponse) and not isinstance(response, HtmlResponse):
            # 重新构造 HtmlResponse 返回
            return HtmlResponse(
                url=response.url,
                body=response.body,
                encoding=response.encoding,
                request=request
            )
        return response

然后在 settings.py 里启用它:

DOWNLOADER_MIDDLEWARES = {
    '你的项目名.middlewares.ForceHtmlResponseMiddleware': 543,
}

内容的提问来源于stack exchange,提问作者Fernando César

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 20:31:13