首页 > 解决方案 > 如何将自定义规则添加到 spaCy 标记器以将 HTML 分解为单个标记?

问题描述

我知道有很多资源可以解决这个问题,但我无法让 spaCy 完全按照我的意愿去做。

我想向我的 spaCy 标记器添加规则,以便我的文本中的 HTML 标记(例如<br/>等)成为单个标记。

我现在正在使用“merge_noun_chunks”管道,所以我得到了这样的令牌:(
"documentation<br/>The Observatory Safety System"这是一个单一的令牌)

我想添加一条规则,以便将其拆分为 3 个标记:
"documentation", "<br/>", "The Observatory Safety System"
我查找了很多资源:这里也在这里。但我无法让它在我的情况下工作

我试过这个:

    
    infix_re = re.compile(r'''<[\w+]\/>''')
    prefix_re = compile_prefix_regex(nlp.Defaults.prefixes)
    suffix_re = compile_suffix_regex(nlp.Defaults.suffixes)

    return Tokenizer(nlp.vocab, prefix_search=prefix_re.search,
                                suffix_search=suffix_re.search,
                                infix_finditer=infix_re.finditer,
                                token_match=None)

我不确定我是否完全理解更改中缀的作用。我还应该按照这里的建议<从前缀中删除吗?

标签: pythonparsingspacy

解决方案


实现这一点的一种方法似乎涉及使标记器

  1. 分解包含没有空格的标记的标记,以及
  2. “块”标签状序列作为单个标记。

要拆分示例中的标记,您可以修改标记器中缀(以此处描述的方式):

infixes = nlp.Defaults.infixes + [r'([><])']
nlp.tokenizer.infix_finditer = spacy.util.compile_infix_regex(infixes).finditer

为确保标签被视为单个标记,您可以使用“特殊情况”(请参阅​​标记器概述方法文档)。您将为打开、关闭和空标签添加特殊情况,例如:

# open and close
for tagName in "html body i br p".split():
    nlp.tokenizer.add_special_case(f"<{tagName}>", [{ORTH: f"<{tagName}>"}])    
    nlp.tokenizer.add_special_case(f"</{tagName}>", [{ORTH: f"</{tagName}>"}])    

# empty
for tagName in "br p".split():
    nlp.tokenizer.add_special_case(f"<{tagName}/>", [{ORTH: f"<{tagName}/>"}])    

综合起来:

import spacy
from spacy.symbols import ORTH

nlp = spacy.load("en_core_web_trf")
infixes = nlp.Defaults.infixes + [r'([><])']
nlp.tokenizer.infix_finditer = spacy.util.compile_infix_regex(infixes).finditer

for tagName in "html body i br p".split():
    nlp.tokenizer.add_special_case(f"<{tagName}>", [{ORTH: f"<{tagName}>"}])    
    nlp.tokenizer.add_special_case(f"</{tagName}>", [{ORTH: f"</{tagName}>"}])    

for tagName in "br p".split():
    nlp.tokenizer.add_special_case(f"<{tagName}/>", [{ORTH: f"<{tagName}/>"}])    

这似乎产生了预期的结果。例如,申请...

text = """<body>documentation<br/>The Observatory <p> Safety </p> System</body>"""
print("Tokenized:")
for t in nlp(text):
    print(t)

... 将完整且独立地打印标签:

# ... snip
documentation
<br/>
The
# ... snip

我发现标记器的解释方法在这种情况下非常有用。它为您提供了标记化原因的细分。


推荐阅读