【问题标题】:Python extract information from paragraphPython从段落中提取信息
【发布时间】:2019-10-14 18:48:12
【问题描述】:

我是 Python 新手,现在我正试图从一组包含员工相关统计数据的段落中提取信息。

例如,段落可能如下所示:

姓名 Rakesh Rao 年龄 34 性别 男性 婚姻状况 单身

整个文本没有被任何逗号分隔,所以我很难区分这些信息。 此外,有时变量名称后可能有一个冒号,有时可能没有。例如,在第 1 行,它是 "Name Rakesh Rao",但在第 2 行,它是 "Name: Ramachandra Deshpande"

这些信息大约有 1400 条记录,所以如果我不必手动分离这些信息,那就太好了。 有人能帮忙吗?我将非常感激!

【问题讨论】:

    标签: python regex text text-extraction


    【解决方案1】:

    好吧,我想你可以尝试使用正则表达式来做到这一点。 如果您的文字正是这样:

    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&lt;name_of_the_group&gt;…)。我使用命名组只是为了让以后更容易更好地提取信息,使用m.group('name'),其中m 是一个匹配对象。

    \D+ 表示“至少一个非数字字符”。这会捕获所有字母、下划线以及空格。这就是为什么字段的顺序对于这个特定的表达式如此重要的原因。如果您要更改顺序并将Gender 字段放在NameAge 之间,它也会捕获它,因为+ 修饰符是贪婪的。

    另一方面,下“行”中的\d+ 表示“至少一个数字字符”,因此介于 0 和 9 之间。

    我希望解释已经足够了,但是在这个非常有用的网站上使用该表达式可能对您有用:

    https://regex101.com/r/N5ZJU9/2

    我已经为你输入了正则表达式和测试字符串。

    【讨论】:

    • 伙计,你疯了!这非常强大,正是我所需要的。非常非常感谢!
    • 我很乐意提供帮助!如果我是正确的,这些字段是在不同的行上,你介意编辑问题以匹配这个事实吗?另外,如果您需要解释我写的表达式的语法,我也可以将其添加到我的答案中。
    • 哦,这些字段实际上是在同一个段落中的。如果您有时间,请帮助我了解语法。谢谢!
    • 我的意思是所有数据都在同一行。
    • 完成了,希望这个小小的解释对你有所帮助。
    【解决方案2】:

    您可以匹配可选字符,在您的情况下是 : 与以下表达式 [:]?

    根据提供的信息,这个正则表达式应该提取所需的信息:

    ^Name[:]?\s([A-Z][-'a-zA-Z]+)\s([A-Z][-'a-zA-Z]+)$
    

    您可以查看here。 此正则表达式将匹配两个单词的名称。还有包含-' 的名称。 在 Python 中,这可能看起来像这样:

    regex = r"^Name[:]?\s([A-Z][-'a-zA-Z]+)\s([A-Z][-'a-zA-Z]+)$"    
    test_str = ("Name Rakesh Rao\n"
        "Name: Ramachandra Deshpande")    
    matches = re.finditer(regex, test_str, re.MULTILINE)
    

    您也可以通过上面提供的链接查看此示例。

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      如果字段名称始终在字符串中,您可以在这些字段名称上拆分字符串。例如:

      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 工具包从文本中删除所有类型的特殊字符。请小心,因为名称中也可能包含特殊字符。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-14
        • 2011-07-15
        • 2020-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-20
        • 2012-12-26
        相关资源
        最近更新 更多