我是Python的新手,现在我正在尝试从一组包含员工相关统计数据的段落中提取信息。
例如,该段落可能如下所示:
姓名 Rakesh Rao 年龄 34 性别 男性 婚姻状况 单身
整个文本没有被任何逗号分隔,所以我很难将这些信息分开。 此外,有时变量名称后可能会有一个冒号,有时可能没有。例如,在第 1 行中,它是"Name Rakesh Rao"
,但在第 2 行中它是"Name: Ramachandra Deshpande"
。
这些信息大约有 1400 条记录,因此如果我不必手动分离信息,那就太好了。 谁能帮忙?我将非常感激!
好吧,我想你可以尝试使用正则表达式来做到这一点。 如果你的文字正是这样:
paragraph = 'Name Rakesh Rao Age 34 Gender Male Marital Status Single'
您可以使用此正则表达式(必须先import re
(:
m = re.fullmatch(
(
r'Name(?::)? (?P<name>D+) ' # pay attention to the space at the end
r'Age(?::)? (?P<age>d+) '
r'Gender(?::)? (?P<gender>D+) '
r'Marital Status(?::)? (?P<status>D+)' # no space here, since the string ends
),
paragraph
)
然后,您可以使用正则表达式中定义的组的名称,如下所示:
>>> m.group('name')
'Rakesh Rao'
>>> m.group('age')
'34'
>>> m.group('gender')
'Male'
>>> m.group('status')
'Single'
如果所有字段都在一行中,则只需将n
替换为正则表达式中的单个空格即可。
请注意,这将支持紧跟在行名后面的单个逗号,如下所示:
Name: Rakesh Rao
但它不支持不同的数据顺序。如果你也愿意,我可以尝试写一个不同的表达式。
表达式的解释
让我们取表达式的第一"行":
r'Name(?::)? (?P<name>D+) '
首先,为什么r'…'
字符串语法?这只是为了避免双反斜杠。在"典型"字符串中,我们需要像这样编写表达式:
'Name(?:\:)? (?P<name>\D+) '
现在,到实际的表达。第一部分,Name
,很明显。
(?::)?
这部分创建了一个内部带有冒号的非捕获组((?:…)
- 它是:
而不仅仅是:
,因为冒号本身是正则表达式语法的一部分。非捕获组,因为这个冒号对我们来说真的无关紧要。
然后,在单个空格之后,我们有这个:
(?P<name>D+)
这将创建一个命名组,语法为(?P<name_of_the_group>…)
。我使用命名组只是为了方便以后使用m.group('name')
提取信息,其中m
是一个匹配对象。
D+
表示"至少一个非数字字符"。这将捕获所有字母、下划线以及空格。这就是为什么字段的顺序对于这个特定的表达式如此重要的原因。如果您要更改顺序并将Gender
字段放在Name
和Age
之间,它也会捕获它,因为+
修饰符是贪婪的。
另一方面,下一个"行"中的d+
表示"至少一个数字字符",因此介于 0 和 9 之间。
我希望这个解释就足够了,但在这个非常有用的网站上,在这里玩这个表达式可能对你有用:
https://regex101.com/r/N5ZJU9/2
我已经为您输入了正则表达式和测试字符串。
您可以匹配可选字符,在您的情况下,使用以下表达式[:]?
:
。
根据提供的信息,此正则表达式应提取所需的信息:
^Name[:]?s([A-Z][-'a-zA-Z]+)s([A-Z][-'a-zA-Z]+)$
你可以在这里查看。 此正则表达式将匹配两个单词的名称。还包含-'
的名称。 在 Python 中,这可能看起来像这样:
regex = r"^Name[:]?s([A-Z][-'a-zA-Z]+)s([A-Z][-'a-zA-Z]+)$"
test_str = ("Name Rakesh Raon"
"Name: Ramachandra Deshpande")
matches = re.finditer(regex, test_str, re.MULTILINE)
您也可以通过上面提供的链接查看此示例。
希望这有帮助。
如果字段名称始终在字符串中,则可以拆分这些字段名称上的字符串。例如:
str_to_split = "Name Rakesh Rao Age 34 Gender Male Marital Status Single"
splitted = str_to_split.split("Age")
name = splitted[0].replace("Name", "")
例如,如果您的文本仍包含其他字符,则可以使用replace(":", "")
删除它们。否则,您可以使用 NLTK 工具包从文本中删除所有类型的特殊字符。要小心,因为名称中也可能包含特殊的字符。