不写callback时,Scrapy仅对start_requests或start_urls发起的Request默认调用parse;手动yield Request漏掉callback会导致响应被丢弃且无警告。

Request 里 callback 不写会怎样
不写 callback 参数,Scrapy 默认调用 parse 方法——但仅限于该 Request 是从 start_requests 或 start_urls 自动发起的。手动 yield Request(url=...) 时漏掉 callback,请求发出去了,但没人处理响应,页面内容直接丢弃,日志里连 warning 都没有。
常见错误现象:scrapy crawl myspider 看似运行成功,但 parse 函数完全没被调用,item 一个都不出,log 里只有 DEBUG: Crawled (200) 却无后续。
- 显式写
callback=self.parse,哪怕目标就是默认方法,也别省 - 如果要进另一个解析函数(比如
parse_detail),必须写全callback=self.parse_detail - 回调函数名必须是 spider 类里的实例方法,不能是字符串或未定义的名称
parse 函数里 yield Request 的三个关键参数
yield Request 在 parse 中最常用来翻页或跳详情页,但容易因参数误配导致重定向失败、丢失 cookies 或编码错乱。
使用场景:列表页提取多个详情链接,逐个请求并解析;或分页链接循环请求下一页。
-
url:必须是完整 URL(https://...)或相对于当前响应的路径(response.urljoin('/item/123'))。直接写/item/123而不 join,会变成http://example.com/item/123(根路径拼接),不是你想要的 -
callback:如上所述,必须显式指定,且函数存在、可调用 -
meta:传参唯一合法方式。比如把标题从列表页带到详情页:meta={'title': title},然后在parse_detail里用response.meta['title']取回
示例:
def parse(self, response):
for url in response.css('a::attr(href)').getall():
yield scrapy.Request(
url=response.urljoin(url),
callback=self.parse_detail,
meta={'source_url': response.url}
)
为什么 parse 函数不能 return Response 对象
parse 函数必须 yield 或 return 可迭代对象(Request、Item、字典等),绝不能返回 response 本身。Scrapy 内部靠生成器协议驱动流程,返回 response 会导致 TypeError: 'HtmlResponse' object is not iterable。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
常见错误现象:调试时想“先看看 response”,随手写 return response,结果爬虫立即报错退出,log 里只有一行 traceback。
- 想看响应内容,用
print(response.text[:200])或logging.debug(response.url) - 想中断当前解析(比如检测到反爬页),用
return(空返回)或return [],不 yield 任何东西即可 - 需要修改请求头或 cookies?在
Request构造时用headers=...或cookies=...参数,而不是动 response
callback 函数里 request.meta 丢失的典型原因
meta 是 Scrapy 唯一推荐的跨请求传参机制,但它不是永久存储——一旦中间经过重定向(302)、重试(retry)、或中间件拦截(如 RedirectMiddleware 关闭),meta 默认会丢失。
性能 / 兼容性影响:开启 handle_httpstatus_list = [302] 并手动处理重定向时,meta 保留;但默认行为下,302 后新 response 的 meta 是空字典。
- 确保关键数据加
meta={'dont_redirect': True}强制禁用重定向(慎用,可能跳过必要跳转) - 更稳妥做法:在中间件中继承
RedirectMiddleware,重写process_response,手动拷贝request.meta - 简单场景下,把数据塞进 URL query(如
?title=xxx)再解析,虽丑但稳定
容易被忽略的地方:很多人以为 meta 像全局变量一样“自动传递”,其实它只随原始 Request 实例走,中间任何一次框架级重定向都会切断它。真要传参,得主动管住重定向链。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










