Ble*_*der 8 python parsing nlp machine-learning
我正在尝试从包含人员条目的几个大型文本文件中提取数据.但问题是,我无法控制数据的来源.
它通常采用以下格式:
LASTNAME,名字中间名(也许是昵称)为什么这个文本在这里2012年1月25日
姓氏姓氏2001一些我不关心的文字
姓氏,名字等等... 2012年1月25日......
目前,我使用的是巨大的,其分离所有的正则表达式kindaCamelcase的话,那有上涨到年底每月名和名称很多特殊情况下的所有单词.然后我使用更多正则表达式来提取名称和日期的许多组合.
这似乎不是最佳的.
是否有任何用于Python的机器学习库可以解析格式错误的数据?
我试过NLTK,但它无法处理我的脏数据.我现在正在修补Orange,我喜欢它的OOP风格,但我不确定我是否在浪费时间.
理想情况下,我想做这样的事情来训练解析器(具有许多输入/输出对):
training_data = (
'LASTNAME, Firstname Middlename (Maybe a Nickname)FooBarJanuary 25, 2012',
['LASTNAME', 'Firstname', 'Middlename', 'Maybe a Nickname', 'January 25, 2012']
)
Run Code Online (Sandbox Code Playgroud)
这样的事情是可能的,还是我高估了机器学习?任何建议将不胜感激,因为我想更多地了解这个主题.
我最终实现了一系列有点复杂的详尽正则表达式,其中包含使用基于文本的“过滤器”的所有可能的用例,这些过滤器在加载解析器时被替换为适当的正则表达式。
如果有人对代码感兴趣,我会将其编辑到这个答案中。
这基本上就是我用过的。为了用我的“语言”构造正则表达式,我必须创建替换类:
class Replacer(object):
def __call__(self, match):
group = match.group(0)
if group[1:].lower().endswith('_nm'):
return '(?:' + Matcher(group).regex[1:]
else:
return '(?P<' + group[1:] + '>' + Matcher(group).regex[1:]
Run Code Online (Sandbox Code Playgroud)
然后,我创建了一个泛型Matcher类,它为给定模式名称的特定模式构造了一个正则表达式:
class Matcher(object):
name_component = r"([A-Z][A-Za-z|'|\-]+|[A-Z][a-z]{2,})"
name_component_upper = r"([A-Z][A-Z|'|\-]+|[A-Z]{2,})"
year = r'(1[89][0-9]{2}|20[0-9]{2})'
year_upper = year
age = r'([1-9][0-9]|1[01][0-9])'
age_upper = age
ordinal = r'([1-9][0-9]|1[01][0-9])\s*(?:th|rd|nd|st|TH|RD|ND|ST)'
ordinal_upper = ordinal
date = r'((?:{0})\.? [0-9]{{1,2}}(?:th|rd|nd|st|TH|RD|ND|ST)?,? \d{{2,4}}|[0-9]{{1,2}} (?:{0}),? \d{{2,4}}|[0-9]{{1,2}}[\-/\.][0-9]{{1,2}}[\-/\.][0-9]{{2,4}})'.format('|'.join(months + months_short) + '|' + '|'.join(months + months_short).upper())
date_upper = date
matchers = [
'name_component',
'year',
'age',
'ordinal',
'date',
]
def __init__(self, match=''):
capitalized = '_upper' if match.isupper() else ''
match = match.lower()[1:]
if match.endswith('_instant'):
match = match[:-8]
if match in self.matchers:
self.regex = getattr(self, match + capitalized)
elif len(match) == 1:
elif 'year' in match:
self.regex = getattr(self, 'year')
else:
self.regex = getattr(self, 'name_component' + capitalized)
Run Code Online (Sandbox Code Playgroud)
最后,还有通用Pattern对象:
class Pattern(object):
def __init__(self, text='', escape=None):
self.text = text
self.matchers = []
escape = not self.text.startswith('!') if escape is None else False
if escape:
self.regex = re.sub(r'([\[\].?+\-()\^\\])', r'\\\1', self.text)
else:
self.regex = self.text[1:]
self.size = len(re.findall(r'(\$[A-Za-z0-9\-_]+)', self.regex))
self.regex = re.sub(r'(\$[A-Za-z0-9\-_]+)', Replacer(), self.regex)
self.regex = re.sub(r'\s+', r'\\s+', self.regex)
def search(self, text):
return re.search(self.regex, text)
def findall(self, text, max_depth=1.0):
results = []
length = float(len(text))
for result in re.finditer(self.regex, text):
if result.start() / length < max_depth:
results.extend(result.groups())
return results
def match(self, text):
result = map(lambda x: (x.groupdict(), x.start()), re.finditer(self.regex, text))
if result:
return result
else:
return []
Run Code Online (Sandbox Code Playgroud)
它变得相当复杂,但它有效。我不会发布所有源代码,但这应该可以让人们开始。最后,它转换了一个这样的文件:
$LASTNAME, $FirstName $I. said on $date
Run Code Online (Sandbox Code Playgroud)
进入带有命名捕获组的已编译正则表达式。
| 归档时间: |
|
| 查看次数: |
1640 次 |
| 最近记录: |