如何在Spacy中获取包含指定Span/Token的句子编号?
获取Spacy PhraseMatcher匹配结果对应的句子编号
当然可以实现,核心是先让Spacy对文档进行分句,再通过匹配到的Span确定其所属句子的索引。
关键说明
你之前的代码禁用了部分组件,但句子分割需要依赖Spacy的分句功能。可以通过保留parser组件(能提供更准确的分句结果),或者添加轻量的sentencizer组件来实现分句。
修改后的示例代码
from spacy.matcher import PhraseMatcher import spacy from spacy.tokens import Span # 方案1:保留parser组件实现分句(推荐,分句更准确) nlp = spacy.load("en_core_web_sm", disable=["ner", 'lemmatizer', 'attribute_rules']) # 方案2:用轻量sentencizer组件(适合追求速度的场景) # nlp = spacy.load("en_core_web_sm", disable=["ner", 'lemmatizer', 'attribute_rules', 'tagger', 'parser']) # nlp.add_pipe("sentencizer") matcher = PhraseMatcher(nlp.vocab, attr="LOWER") matcher.add("obama", [nlp("Barack Obama"), nlp("Baracko Obama"), nlp("Baracko OBAMA")]) doc = nlp("BARACK OBAMA lifts America one last time in emotional. Farewell Baracko Obama baracko obama") # 先提取文档的所有句子 sentences = list(doc.sents) matches = matcher(doc) # 存储匹配结果及对应句子编号 result_with_sent_num = [] for match_id, start, end in matches: span = Span(doc, start, end) # 遍历句子,找到包含当前span的句子 for sent_idx, sent in enumerate(sentences): # 句子的token范围是[sent.start, sent.end),匹配span的起始token位置即可判断归属 if sent.start <= start < sent.end: result_with_sent_num.append({ "匹配文本": span.text, "匹配位置": (start, end), "句子编号": sent_idx + 1 # 转为从1开始的编号 }) break # 输出结果 print("匹配结果与对应句子编号:") for item in result_with_sent_num: print(f"{item['匹配文本']} -> 第{item['句子编号']}句,token位置:{item['匹配位置']}")
输出结果
匹配结果与对应句子编号: BARACK OBAMA -> 第1句,token位置:(0, 2) Baracko Obama -> 第2句,token位置:(11, 13) baracko obama -> 第2句,token位置:(13, 15)
核心逻辑
- 通过
doc.sents获取文档的句子列表,每个句子对象自带start和end属性,对应其在文档中的token起始、结束位置。 - 对每个匹配结果的起始token位置
start,判断它落在哪个句子的[sent.start, sent.end)区间内,该句子的索引(+1转为从1开始的编号)就是对应的句子编号。
内容的提问来源于stack exchange,提问作者bib
相关产品推荐
相关产品推荐

