如何使用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
相关产品推荐
相关产品推荐

