如何使用Scrapy提取数量不确定的<p>标签文本并合并存储?
Scrapy 适配两类页面的不定长段落采集实现
核心逻辑不用提前固定p标签数量,顺着DOM同级节点遍历,遇到非p标签(即下一个章节起始位置)就终止,天然适配不同页面的结构差异、段落数量差异。
具体实现步骤
- 首先锁定内容范围:先选中
<div class="entry-content">容器,所有后续选择都在这个容器内执行,避免抓取到页面其他区域的无关内容。 - 兼容定位起始标题:写通用XPath同时匹配两类目标标题:文本包含
Characteristics的h2标签、文本包含Diet的h3标签,用normalize-space()处理文本前后的空白字符,避免排版空格导致匹配失败。 - 逐节点遍历抓连续p:从定位到的标题节点开始,逐个取后面的第一个同级节点判断:
- 如果当前节点是p标签,就提取清洗后的文本存入临时列表
- 如果当前节点不是p标签(比如下一个h2/h3标题、列表、div块等),立刻终止遍历,不会越界抓到其他章节的内容
- 最后把临时列表里的所有段落文本拼接成完整文本块,存入对应item字段即可。
可直接复用的解析代码
import scrapy class ContentSpider(scrapy.Spider): name = 'content_spider' # 替换成实际起始url列表 start_urls = ['https://example.com/page1', 'https://example.com/page2'] def parse(self, response): item = {} # 锁定内容容器 content_wrap = response.xpath('//div[@class="entry-content"]') # 匹配两类目标起始标题 title_node = content_wrap.xpath( './*[(self::h2 and contains(normalize-space(./text()), "Characteristics")) ' 'or (self::h3 and contains(normalize-space(./text()), "Diet"))]' ) section_paragraphs = [] if title_node: # 从标题的下一个同级节点开始遍历 current = title_node[0].xpath('./following-sibling::*[1]') while current: # 判断当前节点是否为p标签 if current.xpath('self::p'): p_text = current.xpath('normalize-space(.)').get('').strip() if p_text: section_paragraphs.append(p_text) # 移动到下一个同级节点 current = current.xpath('./following-sibling::*[1]') else: # 碰到非p节点直接终止,避免跨章节抓取 break # 合并文本存入对应字段,字段名替换成实际item里的字段名即可 item['target_section_content'] = '\n'.join(section_paragraphs) yield item
避坑说明
- 不要直接用
following-sibling::p一次性选所有后续p标签,这种写法会跳过中间的其他标签、把后面其他章节的p也抓进来,准确性没有逐节点判断高。 - 不需要为两类页面单独写两套解析逻辑,上述代码已经兼容h2/h3两种标题层级,不管标题后有1个还是十几个连续p标签都能完整抓取,适配不同页面的段落数量差异。
- 提取文本时统一用
normalize-space()处理,会自动去掉文本前后的换行、多余空格,避免拼接后出现大量无意义空白。
内容的提问来源于stack exchange,提问作者cleexiang
相关产品推荐
相关产品推荐

