Spacy自定义规则匹配问题:无法正确提取邮箱、手机号等信息
问题分析
你的匹配模式[{"LOWER": "email"}, {"LOWER": "phone"}]要求**"email"和"phone"两个词连续相邻出现**,但目标文本里"email"后跟着冒号和邮箱地址,"phone"在逗号之后,两者并不连续,因此匹配器无法找到符合条件的结果。
解决方案
根据你提取邮箱、手机号的需求,提供两种可行实现方式:
方式一:用Spacy Matcher提取标签对应内容
通过定义更灵活的匹配模式,定位"email:"/"phone:"标签后的目标内容:
import spacy from spacy.matcher import Matcher nlp = spacy.load("en_core_web_sm") matcher = Matcher(nlp.vocab) # 匹配邮箱:"email" + 冒号 + 可选空格 + 邮箱格式文本 email_pattern = [ {"LOWER": "email"}, {"ORTH": ":"}, {"IS_SPACE": True, "OP": "?"}, # 匹配可选空格 {"TEXT": {"REGEX": r"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+"}} ] # 匹配手机号:"phone" + 冒号 + 可选空格 + 数字序列 phone_pattern = [ {"LOWER": "phone"}, {"ORTH": ":"}, {"IS_SPACE": True, "OP": "?"}, {"LIKE_NUM": True} ] matcher.add("EMAIL", [email_pattern]) matcher.add("PHONE", [phone_pattern]) my_text = "email: kashif.jilani@sample.com, phone: 1234567" my_doc = nlp(my_text) matches = matcher(my_doc) for match_id, start, end in matches: entity_type = nlp.vocab.strings[match_id] # 跳过标签、冒号和空格,提取核心内容 content_start = start + 3 if entity_type == "EMAIL" else start + 3 content_span = my_doc[content_start:end] print(f"{entity_type}: {content_span.text}")
方式二:用正则表达式直接提取
如果不需要依赖Spacy的NLP能力,直接用Python内置正则模块更高效:
import re my_text = "email: kashif.jilani@sample.com, phone: 1234567" # 提取邮箱 email_match = re.search(r"email:\s*([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)", my_text, re.IGNORECASE) if email_match: print(f"EMAIL: {email_match.group(1)}") # 提取手机号 phone_match = re.search(r"phone:\s*(\d+)", my_text, re.IGNORECASE) if phone_match: print(f"PHONE: {phone_match.group(1)}")
附加:若仅需匹配"email"/"phone"标签词
如果你的需求只是定位文本中的"email"和"phone"这两个词,修改模式为匹配单个词即可:
import spacy from spacy.matcher import Matcher nlp = spacy.load("en_core_web_sm") matcher = Matcher(nlp.vocab) # 匹配"email"或"phone"单个词 pattern = [{"LOWER": {"IN": ["email", "phone"]}}] matcher.add("CONTACT_LABEL", [pattern]) my_text = "email: kashif.jilani@sample.com, phone: 1234567" my_doc = nlp(my_text) matches = matcher(my_doc) for match_id, start, end in matches: span = my_doc[start:end] print(span.text)
内容的提问来源于stack exchange,提问作者Kashif Jilani
相关产品推荐
相关产品推荐

