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

