从文本Python中识别和提取日期的最佳方法?

red*_*dct 29 python parsing nlp date

作为我正在开展的一个更大的个人项目的一部分,我试图从各种文本来源中分离出内联日期.

例如,我有一个很大的字符串列表(通常采用英语句子或语句的形式),采用多种形式:

中央设计委员会会议于10月22日星期二下午6:30举行

Th 9/19 LAB:串行编码(第2.2节)

对于那些今天无法成功的人,将在12月15日再举行一次.

练习册3(最低工资):截止于9月18日星期三晚上11:59

他将于9月15日飞行.

虽然这些日期与自然文本一致,但它们本身都不是特定的自然语言形式(例如,没有"会议将从明天开始两周" - 这一切都是明确的).

作为对这种处理没有太多经验的人,最好的开始是什么?我已经研究了dateutil.parser模块和解析时间之类的东西,但是这些似乎是你隔离了日期之后.

因此,有没有什么好方法可以提取日期和无关文本

input:  Th 9/19 LAB: Serial encoding (Section 2.2)
output: ['Th 9/19', 'LAB: Serial encoding (Section 2.2)']
Run Code Online (Sandbox Code Playgroud)

或类似的东西?似乎这种处理是由Gmail和Apple Mail等应用程序完成的,但它是否可以在Python中实现?

ako*_*ian 24

我也在寻找解决方案,找不到任何解决方案,所以我和朋友建立了一个工具来做到这一点.我以为我会回来分享其他人发现它有用.

datefinder - 在文本中查找和提取日期

  • 确实很棒的工具,它解决了各种各样的情况!做得好。 (3认同)
  • 是否可以获取原始字符串列表?例如:“条目将于 2017 年 1 月 4 日晚上 8:00 截止”,如果我像这样运行:matches = datefinder.find_dates(text) 将返回 ['January 4th, 2017 at 8:00pm'] (2认同)
  • @akoumjian 感谢提供这么棒的工具!但是我想知道我们是否可以在实际文本中获取日期标记的位置或索引? (2认同)

Afs*_*ati 12

我很惊讶没有提到SUTimedateparser 的 search_dates方法。

from sutime import SUTime
import os
import json
from dateparser.search import search_dates

str1 = "Let's meet sometime next Thursday" 

# You'll get more information about these jar files from SUTime's github page
jar_files = os.path.join(os.path.dirname(__file__), 'jars')
sutime = SUTime(jars=jar_files, mark_time_ranges=True)

print(json.dumps(sutime.parse(str1), sort_keys=True, indent=4))
"""output: 
[
    {
        "end": 33,
        "start": 20,
        "text": "next Thursday",
        "type": "DATE",
        "value": "2018-10-11"
    }
]
"""

print(search_dates(str1))
#output:
#[('Thursday', datetime.datetime(2018, 9, 27, 0, 0))]
Run Code Online (Sandbox Code Playgroud)

尽管我尝试过其他模块,如 dateutil、datefinder 和 natty(无法让小鸭与 python 一起工作),但这两个似乎给出了最有希望的结果。

SUTime 的结果更可靠,从上面的代码片段中可以清楚地看出。但是,SUTime 在一些基本场景中失败,比如解析文本

“我要到 9/19 才有空”

或者

“我将在(9 月 18 日至 9 月 20 日)之间不可用。

它没有给出第一个文本的结果,只给出第二个文本的月份和年份。然而,这在 search_dates 方法中处理得很好。search_dates 方法更具侵略性,将提供与输入文本中的任何单词相关的所有可能日期。

我还没有找到一种方法来严格解析 search_methods 中的日期的文本。如果我能找到一种方法来做到这一点,它将是我的首选 SUTime,如果我找到它,我也会确保更新此答案。


Kyl*_*ley 7

如果您可以识别实际包含日期信息的段,则使用parsedatetime解析它们可能相当简单.有一些事情需要考虑,即你的日期没有多年,你应该选择一个地区.

>>> import parsedatetime
>>> p = parsedatetime.Calendar()
>>> p.parse("December 15th")
((2013, 12, 15, 0, 13, 30, 4, 319, 0), 1)
>>> p.parse("9/18 11:59 pm")
((2014, 9, 18, 23, 59, 0, 4, 319, 0), 3)
>>> # It chooses 2014 since that's the *next* occurence of 9/18
Run Code Online (Sandbox Code Playgroud)

当你有无关的文本时,它并不总是完美的.

>>> p.parse("9/19 LAB: Serial encoding")
((2014, 9, 19, 0, 15, 30, 4, 319, 0), 1)
>>> p.parse("9/19 LAB: Serial encoding (Section 2.2)")
((2014, 2, 2, 0, 15, 32, 4, 319, 0), 1)
Run Code Online (Sandbox Code Playgroud)

老实说,这似乎是一种简单到足以解析特定格式并从每个句子中挑出最可能的问题.除此之外,这将是一个体面的机器学习问题.

  • 我想问一个更好的问题是:什么是自动识别细分市场的最佳方式?是否有某种方法(除了巨大的正则表达式,我猜)来识别日期子字符串? (4认同)

小智 7

import datefinder
string_with_dates = """
                    entries are due by January 4th, 2017 at 8:00pm
                    created 01/15/2005 by ACME Inc. and associates.
                    """
matches = datefinder.find_dates(string_with_dates)
for match in matches:
    print match
Run Code Online (Sandbox Code Playgroud)


Sam*_*ain 6

您可以将dateutil 模块parse方法与fuzzy选项一起使用。

>>> from dateutil.parser import parse
>>> parse("Central design committee session Tuesday 10/22 6:30 pm", fuzzy=True)
datetime.datetime(2018, 10, 22, 18, 30)
>>> parse("There will be another one on December 15th for those who are unable to make it today.", fuzzy=True)
datetime.datetime(2018, 12, 15, 0, 0)
>>> parse("Workbook 3 (Minimum Wage): due Wednesday 9/18 11:59pm", fuzzy=True)
datetime.datetime(2018, 3, 9, 23, 59)
>>> parse("He will be flying in Sept. 15th.", fuzzy=True)
datetime.datetime(2018, 9, 15, 0, 0)
>>> parse("Th 9/19 LAB: Serial encoding (Section 2.2)", fuzzy=True)
datetime.datetime(2002, 9, 19, 0, 0)
Run Code Online (Sandbox Code Playgroud)