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

如何使用Scrapy获取未知位置<p>标签中的事件描述文本?

回答

嘿,这个问题其实挺常见的——当目标内容没有固定位置或专属类名时,我们可以通过排除法或者上下文关联来定位想要的<p>标签。下面给你几个实用的方案:

方案1:基于内容特征过滤(推荐)

观察你要提取的描述,它们有几个明显特征:

  • 不包含<strong>标签(不是纯加粗文本)
  • 不是空段落
  • 不包含“Learn More”按钮链接

你可以在Scrapy的Selector里用XPath或CSS选择器来筛选:

使用XPath的写法:

# 先定位每个活动的标题区块
activities = response.xpath('//div[@class="templatecontent"]/h3')
for activity in activities:
    # 获取当前标题后第一个符合条件的描述段落
    description = activity.xpath('following-sibling::p[not(strong) and not(a) and normalize-space(.) != ""][1]/text()').get()
    print(description)

解释一下这个XPath的逻辑:

  • following-sibling::p:选取当前<h3>之后的所有同级<p>标签
  • not(strong):排除包含加粗标签的段落(比如时间、主讲人这类信息)
  • not(a):排除包含按钮链接的段落
  • normalize-space(.) != "":过滤掉空段落
  • [1]:取第一个匹配到的结果(也就是我们要的活动描述)

使用CSS选择器的写法:

如果你更习惯CSS语法,可以结合手动过滤逻辑:

activities = response.css('div.templatecontent h3')
for activity in activities:
    # 遍历标题后续的所有同级p标签
    for p in activity.css('~ p'):
        # 清理段落文本,去掉多余空格和换行
        raw_text = p.css('::text').getall()
        clean_text = ' '.join([t.strip() for t in raw_text if t.strip()])
        # 判断是否为目标描述:不含strong/a标签,且内容非空
        if not p.css('strong, a') and clean_text:
            print(clean_text)
            break  # 找到第一个符合的就停止遍历

方案2:基于区块分割

因为每个活动是被<hr>标签分隔开的,我们可以先把整个templatecontent分割成独立的活动区块,再在每个区块内提取描述:

import scrapy

# 获取所有非hr的节点,用来分割活动
nodes = response.xpath('//div[@class="templatecontent"]/node()[not(self::hr)]')
activity_blocks = []
current_block = []

for node in nodes:
    node_html = node.get()
    if '<h3' in node_html:
        # 遇到新的活动标题,就把当前区块存入列表(如果有的话)
        if current_block:
            activity_blocks.append(current_block)
        current_block = [node_html]
    else:
        current_block.append(node_html)
# 把最后一个活动区块加进去
if current_block:
    activity_blocks.append(current_block)

# 遍历每个活动区块提取描述
for block in activity_blocks:
    block_selector = scrapy.Selector(text=''.join(block))
    # 同样用过滤规则找目标p标签
    description = block_selector.xpath('//p[not(strong) and not(a) and normalize-space(.) != ""]/text()').get()
    print(description)

方案3:进阶方案(机器学习辅助)

如果页面结构经常变化,规则不好维护,你可以结合scrapy-splash渲染页面,再用NLP库(比如spaCy)识别段落的语义,判断哪个是活动描述。不过这个方案成本较高,适合复杂场景。

最后提醒:测试的时候可以用getall()代替get(),查看所有符合条件的元素,再根据实际情况调整过滤规则,确保精准匹配到目标内容。


内容的提问来源于stack exchange,提问作者foragerDev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 14:07:46