使用 SpaCy 和 Python 创建基于规则的匹配以检测地址
Creating Rule-based matching with SpaCy and Python for detecting addresses
前几天开始学习Python's
SpaCy
lib或者NLP。
我想创建基于规则的匹配来检测街道地址。
这是街道名称的示例:
Esplanade 12
Fischerinsel 65
Esplanade 1
62 boulevard d'Alsace
80 avenue Ferdinand de Lesseps
73 avenue de Bouvines
41 Avenue des Pr'es
84 rue du Château
44 rue Sadi Carnot
Bernstrasse 324
Güntzelstrasse 6
80 Rue St Ferréol
75 rue des lieutemants Thomazo
87 cours Franklin Roosevelt
51 rue du Paillle en queue
16 Chemin Des Bateliers
65 rue Reine Elisabeth
91 rue Saint Germain
Grolmanstraße 41
Buelowstrasse 46
Waßmannsdorfer Chaussee 41
Sonnenallee 29
Gotthardstrasse 81
Augsburger Straße 65
Gotzkowskystrasse 41
Holstenwall 69
Leopoldstraße 40
所以,街道名称是这样形成的:
第一种:
<string (thats ending with 'strasse', 'gasse' or 'platz')> + <number>(letter can be attached to number, for examle 34a)
第二种:
<number> + <'rue', 'avenue', 'platz', 'boulevard'> + <multiple strings strings>
第三种:
<titled string> + <number>
但是前两种是90%的情况。
这是代码:
import spacy
from spacy.matcher import Matcher
from spacy import displacy
nlp = spacy.load("en_core_web_trf")
disable = ['ner']
pattern = ['<i do not know how to write contitions for this>']
matcher = Matcher(nlp.vocab)
matcher.add("STREET", [pattern])
text_testing1 = "I live in Güntzelstrasse 16 in Berlin"
text_testing2 = "Send that to 73 rue de Napoleon 56 in Paris"
doc = nlp(text)
result = matcher(doc)
print(result)
我不知道如何为这种识别编写模式,所以我需要帮助。
短语中需要有数字,其中一个字符串必须是 'rue'、'avenue'、'platz'、'boulevard' 或者必须以“strasse”或“gasse”结尾.
这是一个非常简单的例子,只匹配“*strasse [number]”这样的东西:
import spacy
from spacy.matcher import Matcher
nlp = spacy.load("en_core_web_sm")
matcher = Matcher(nlp.vocab)
pattern = [
{"TEXT": {"REGEX": ".*strasse$"}},
{"IS_DIGIT": True}
]
matcher.add("ADDRESS", [pattern])
doc = nlp("I live in Güntzelstrasse 16 in Berlin")
matches = matcher(doc)
for match_id, start, end in matches:
string_id = nlp.vocab.strings[match_id] # Get string representation
span = doc[start:end] # The matched span
print(match_id, string_id, start, end, span.text)
关键部分是图案。通过更改模式,您可以使其匹配更多内容,例如,如果我们想要匹配不仅以 strasse
结尾而且还以 platz
:
结尾的内容
pattern = [
{"TEXT": {"REGEX": ".*(strasse|platz)$"}},
{"IS_DIGIT": True}
]
您还可以添加具有相同标签的多个模式以获得截然不同的结构,例如您的“rue de Napoleon”示例。
Matcher 有很多功能,我真的建议通读 the docs 并尝试一次。
我同意 polm。唯一的问题是您找不到包含数字和字母的地址,例如 examplestrasse 32a。我认为你应该尝试形状,例如:
pattern = [[
{"TEXT": {"REGEX": ".*(strasse|platz)$"}},
{"SHAPE": {"IN": ["ddx", "dx"]}}
]]
其中shape
d为数字,x为小写字母(X为大写)。一定要阅读文档,它们非常适合 spacy
对于基于 @polm23 and @krisograbek 获取(德语)街道名称的更通用的解决方案,我想出了这个模式:
street_labels = ".*(platz|[Ss]tra[ssß]e|str)$"
patterns = [
{"label": "ADR",
"pattern": [
{"TEXT": {"REGEX": street_labels}},
# here might be a punct or not: Müllerstr. 26 or Müllerstr 26
{"IS_PUNCT": True, "OP": "?"},
# house number can have several formats: 2, 26, 266, 2a, 22a, 222a,
# last six ones catch cases at end of sentence. there might be a better solution out there...
{"SHAPE": {"IN": ["d", "dd", "ddd", "dddx", "ddx", "dx", "d.", "dd.", "ddd.", "dx.", "ddx.", "dddx."]}, "OP": "?"}
]},
# if street name has to parts: Müller Straße
{"label": "ADRddd",
"pattern": [
{"SHAPE": "Xxxxx", "OP": "?"},
{"TEXT": "Straße"},
{"IS_PUNCT": True, "OP": "?"},
{"SHAPE": {"IN": ["d", "dd", "ddd", "dddx", "ddx", "dx", "d.", "dd.", "ddd."]}, "OP": "?"}
]}
]
它匹配:
Müllerstr. 26
Müllerstr 26
Müllerstraße
Müllerstraße 26
Müllerplatz
Müllerstraße 26a
Müller Straße 26
有一件事很奇怪:如果门牌号在句子的末尾,那么 Spacy 会将标点添加到标记中。所以这种情况也需要考虑。
要在街道名称前添加门牌号的案例,可以考虑使用可选的SHAPE
。
前几天开始学习Python's
SpaCy
lib或者NLP。
我想创建基于规则的匹配来检测街道地址。
这是街道名称的示例:
Esplanade 12
Fischerinsel 65
Esplanade 1
62 boulevard d'Alsace
80 avenue Ferdinand de Lesseps
73 avenue de Bouvines
41 Avenue des Pr'es
84 rue du Château
44 rue Sadi Carnot
Bernstrasse 324
Güntzelstrasse 6
80 Rue St Ferréol
75 rue des lieutemants Thomazo
87 cours Franklin Roosevelt
51 rue du Paillle en queue
16 Chemin Des Bateliers
65 rue Reine Elisabeth
91 rue Saint Germain
Grolmanstraße 41
Buelowstrasse 46
Waßmannsdorfer Chaussee 41
Sonnenallee 29
Gotthardstrasse 81
Augsburger Straße 65
Gotzkowskystrasse 41
Holstenwall 69
Leopoldstraße 40
所以,街道名称是这样形成的:
第一种:
<string (thats ending with 'strasse', 'gasse' or 'platz')> + <number>(letter can be attached to number, for examle 34a)
第二种:
<number> + <'rue', 'avenue', 'platz', 'boulevard'> + <multiple strings strings>
第三种:
<titled string> + <number>
但是前两种是90%的情况。 这是代码:
import spacy
from spacy.matcher import Matcher
from spacy import displacy
nlp = spacy.load("en_core_web_trf")
disable = ['ner']
pattern = ['<i do not know how to write contitions for this>']
matcher = Matcher(nlp.vocab)
matcher.add("STREET", [pattern])
text_testing1 = "I live in Güntzelstrasse 16 in Berlin"
text_testing2 = "Send that to 73 rue de Napoleon 56 in Paris"
doc = nlp(text)
result = matcher(doc)
print(result)
我不知道如何为这种识别编写模式,所以我需要帮助。 短语中需要有数字,其中一个字符串必须是 'rue'、'avenue'、'platz'、'boulevard' 或者必须以“strasse”或“gasse”结尾.
这是一个非常简单的例子,只匹配“*strasse [number]”这样的东西:
import spacy
from spacy.matcher import Matcher
nlp = spacy.load("en_core_web_sm")
matcher = Matcher(nlp.vocab)
pattern = [
{"TEXT": {"REGEX": ".*strasse$"}},
{"IS_DIGIT": True}
]
matcher.add("ADDRESS", [pattern])
doc = nlp("I live in Güntzelstrasse 16 in Berlin")
matches = matcher(doc)
for match_id, start, end in matches:
string_id = nlp.vocab.strings[match_id] # Get string representation
span = doc[start:end] # The matched span
print(match_id, string_id, start, end, span.text)
关键部分是图案。通过更改模式,您可以使其匹配更多内容,例如,如果我们想要匹配不仅以 strasse
结尾而且还以 platz
:
pattern = [
{"TEXT": {"REGEX": ".*(strasse|platz)$"}},
{"IS_DIGIT": True}
]
您还可以添加具有相同标签的多个模式以获得截然不同的结构,例如您的“rue de Napoleon”示例。
Matcher 有很多功能,我真的建议通读 the docs 并尝试一次。
我同意 polm。唯一的问题是您找不到包含数字和字母的地址,例如 examplestrasse 32a。我认为你应该尝试形状,例如:
pattern = [[
{"TEXT": {"REGEX": ".*(strasse|platz)$"}},
{"SHAPE": {"IN": ["ddx", "dx"]}}
]]
其中shape
d为数字,x为小写字母(X为大写)。一定要阅读文档,它们非常适合 spacy
对于基于 @polm23 and @krisograbek 获取(德语)街道名称的更通用的解决方案,我想出了这个模式:
street_labels = ".*(platz|[Ss]tra[ssß]e|str)$"
patterns = [
{"label": "ADR",
"pattern": [
{"TEXT": {"REGEX": street_labels}},
# here might be a punct or not: Müllerstr. 26 or Müllerstr 26
{"IS_PUNCT": True, "OP": "?"},
# house number can have several formats: 2, 26, 266, 2a, 22a, 222a,
# last six ones catch cases at end of sentence. there might be a better solution out there...
{"SHAPE": {"IN": ["d", "dd", "ddd", "dddx", "ddx", "dx", "d.", "dd.", "ddd.", "dx.", "ddx.", "dddx."]}, "OP": "?"}
]},
# if street name has to parts: Müller Straße
{"label": "ADRddd",
"pattern": [
{"SHAPE": "Xxxxx", "OP": "?"},
{"TEXT": "Straße"},
{"IS_PUNCT": True, "OP": "?"},
{"SHAPE": {"IN": ["d", "dd", "ddd", "dddx", "ddx", "dx", "d.", "dd.", "ddd."]}, "OP": "?"}
]}
]
它匹配:
Müllerstr. 26
Müllerstr 26
Müllerstraße
Müllerstraße 26
Müllerplatz
Müllerstraße 26a
Müller Straße 26
有一件事很奇怪:如果门牌号在句子的末尾,那么 Spacy 会将标点添加到标记中。所以这种情况也需要考虑。
要在街道名称前添加门牌号的案例,可以考虑使用可选的SHAPE
。