Scrapy需显式处理多层级嵌套数据:用XPath //text() 或 string(.) 提取深层文本;从<script>中提取JSON后用jsonpath-ng解析;递归解析动态评论树并透传meta;Pipeline中扁平化结构再入库。

Scrapy 本身不自动处理多层级嵌套数据,必须靠你显式定义解析路径或用递归逻辑展开——否则会漏掉 SKU、子评论、规格参数这类深层字段。
用 XPath //text() 提取任意深度的文本内容
电商商品页常有「标题+副标题+卖点图标+弹窗说明」多层包裹,直接 response.css('div.title').get() 只能拿到最外层标签文本,子标签文字全丢失。
- 用双斜杠
//text()穿透所有嵌套层级:response.xpath('//div[@class="product-title"]//text()').getall(),返回字符串列表,再''.join()拼接 - 更省事的是
string(.):response.xpath('//div[@class="product-title"]').xpath('string(.)').get(),一步拿到完整纯文本(含空格换行,需后续.strip().replace('\n', ' ')) - 注意:如果目标区域含广告 JS 插入内容或异步加载模块,
//text()无法提取,得切到 Selenium 或分析 AJAX 接口
用 jsonpath 解析响应体中的嵌套 JSON 数据
多数电商网站把商品详情、SKU 列表、评论数据藏在 HTML 的 <script> 标签里,类型是 window.__INITIAL_STATE__ = {...} 或直接返回 JSON API。硬写 data['skuList'][0]['specs'][1]['value'] 极易因某层缺失报 KeyError。
- 先用正则或
response.xpath('//script[contains(text(), "INITIAL_STATE")]/text()').get()提取出 JSON 字符串,json.loads()转为 Python 对象 - 用
jsonpath-ng库查路径:parse('$.skuList[*].specs[*].value').find(data),支持通配符和容错,哪怕skuList是空数组也不崩 - 别用
jsonpath_rw(已停更),它不兼容 Python 3.9+;jsonpath-ng是当前唯一活跃维护的实现
用递归 parse 方法处理动态评论树
论坛或商品评论区常见「主评→回复→回复的回复」无限嵌套,HTML 结构每层 class 名可能一致(如都叫 comment-item),但 DOM 深度不确定。
立即学习“Python免费学习笔记(深入)”;
- 不要写 4 层 for 循环硬解;改用递归函数,把当前节点传入,提取本层字段后,再找它的
reply-list子容器,继续调用自身 - 加深度限制(如
max_depth=5),防栈溢出;同时用response.urljoin()处理相对链接,避免下一页请求拼错 - Scrapy 的
Request默认不携带父级上下文,要把必要字段(如主评 ID、层级数)塞进meta参数里透传下去:Request(url, callback=self.parse_reply, meta={'parent_id': pid, 'depth': depth + 1})
Pipeline 中扁平化嵌套结构再入库
直接把带 5 层嵌套的 item 存 MongoDB 或 MySQL,后续查「某个颜色的所有尺寸库存」就得写聚合查询,效率低还容易出错。
- 在自定义 Pipeline 的
process_item里做扁平化:遍历item.get('skus', []),为每个 SKU 生成一个新字典,把商品公共字段(name,category)复制进去,再合并 SKU 特有字段(color,size,stock) - 对评论树也一样:把每层回复都转成独立记录,加
parent_id和level字段,方便数据库按线程回溯 - 别在 Spider 里做扁平化——那会让单个请求逻辑过重,违反 Scrapy “解析快、调度快”的设计初衷
真正难的不是写对第一层解析,而是预判哪一层可能为空、哪一层会突然多出新字段、哪个接口返回结构和文档写的不一致——这些只能靠日志里打 pprint(response.data) 多看几遍真实响应,而不是抄示例代码。


















