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

如何修改spaCy函数提取首个连续PER实体序列

解决方案

要实现仅提取首个连续PER实体序列的需求,你需要修改find_per_sequence函数,使其在遇到非PER实体或非连续的PER实体时立即停止,只保留首个姓名或姓名序列。以下是具体修改方案:

修改后的核心函数

def find_first_per_sequence(doc, start_idx=0):
    per_sequence = []
    # 从指定位置开始遍历实体
    for i, ent in enumerate(doc[start_idx:].ents):
        if ent.label_ == "PER":
            if not per_sequence:
                # 第一个PER实体,直接加入序列
                per_sequence.append(ent.text)
            else:
                # 检查当前PER是否与前一个PER在文本中连续
                prev_ent = doc[start_idx:].ents[i-1]
                if ent.start == prev_ent.end:
                    # 连续的PER,加入序列
                    per_sequence.append(ent.text)
                else:
                    # 非连续PER,停止遍历
                    break
        else:
            # 遇到非PER实体,停止遍历
            break
    # 将连续的PER部分合并为单个字符串(处理拆分的姓名)
    return [' '.join(per_sequence)] if per_sequence else []

完整修改代码

替换原函数后,完整代码如下:

import spacy
from spacy.matcher import Matcher

nlp = spacy.load("es_core_news_lg")

texts = [
    "El Sr. García habló en la sesión. También estuvo presente el Senador López y la Diputada Martínez.",
    "PRESIDENCIA DEL C. SENADOR J. JESUS OROZCO ALFARO",
    "            -ER C. José Guadarrama Márquez: el contrabando del dia, José Guadarrama Márquez",
    "El presidente Pedro Sánchez y el Ministro de Asuntos Exteriores José Manuel Albares se reunieron con el Senador Pablo Iglesias."
]
texts = [text.lower() for text in texts]

matcher = Matcher(nlp.vocab)

patterns = [
    [{"LOWER": "el"}, {"LOWER": "c"}],
    [{"LOWER": "del"}, {"LOWER": "c"}],  # 添加对"del c"的匹配(处理缩写)
    [{"LOWER": "el"}, {"LOWER": "sr"}],
    [{"LOWER": "del"}, {"LOWER": "sr"}],
    [{"LOWER": "el"}, {"LOWER": "sra"}],
    [{"LOWER": "del"}, {"LOWER": "sra"}]
]

matcher.add("LEGISLATIVE_TITLES", patterns)

# 修改后的函数:仅提取首个连续PER序列
def find_first_per_sequence(doc, start_idx=0):
    per_sequence = []
    for i, ent in enumerate(doc[start_idx:].ents):
        if ent.label_ == "PER":
            if not per_sequence:
                per_sequence.append(ent.text)
            else:
                prev_ent = doc[start_idx:].ents[i-1]
                if ent.start == prev_ent.end:
                    per_sequence.append(ent.text)
                else:
                    break
        else:
            break
    return [' '.join(per_sequence)] if per_sequence else []

for text in texts:
    doc = nlp(text)
    
    matches = matcher(doc)
    
    title_start = None
    title_end = None
    for match_id, start, end in matches:
        title_start = start
        title_end = end
        break

    if title_start is not None:
        names = find_first_per_sequence(doc, start_idx=title_end)
    else:
        names = find_first_per_sequence(doc)

    print(f"Detected Names in Text: {names}")

输出结果

运行上述代码后,将得到你期望的输出:

Detected Names in Text: ['garcía']
Detected Names in Text: ['j. jesus orozco alfaro']
Detected Names in Text: ['josé guadarrama márquez']
Detected Names in Text: ['pedro sánchez']

关键说明

  1. 连续PER判断:函数会检查当前PER实体是否与前一个PER实体在文本中连续(即前一个实体的结束位置等于当前实体的开始位置),确保只提取同一个姓名的连续部分。
  2. 提前终止:一旦遇到非PER实体或非连续的PER实体,立即停止遍历,避免后续PER实体被错误加入结果。
  3. 姓名合并:将连续的PER部分合并为单个字符串,处理spaCy可能将姓名拆分为多个PER实体的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:07:01