从Python中的字符串中提取日期


79

如何从“ monkey 2010-07-10 love banana”之类的字符串中提取日期?谢谢!


3
只是一个提示:它以数字开头和结尾。让我考虑一下。尽管regex可以成为您的朋友。
Hamish Grubijan

Answers:


79

如果以固定格式给出日期,则只需使用正则表达式提取日期,然后使用“ datetime.datetime.strptime”来解析日期:

import re
from datetime import datetime

match = re.search(r'\d{4}-\d{2}-\d{2}', text)
date = datetime.strptime(match.group(), '%Y-%m-%d').date()

否则,如果日期以任意形式给出,则无法轻松提取日期。


1
如果它是欧洲格式,例如1980年1月20日表示“ 1980年1月20日”怎么办?如果月/日/年超出合理范围怎么办?
Hamish Grubijan

@lunaryorn在第一个语句中,“ re”是否指代我们要查找所需模式的字符串?
维沙尔

@ vishal.k指的是内置re模块,即import re
lunaryorn

如果有from datetime import datetimeimport datetime
人犯

152

使用python-dateutil

In [1]: import dateutil.parser as dparser

In [18]: dparser.parse("monkey 2010-07-10 love banana",fuzzy=True)
Out[18]: datetime.datetime(2010, 7, 10, 0, 0)

日期无效会引发ValueError

In [19]: dparser.parse("monkey 2010-07-32 love banana",fuzzy=True)
# ValueError: day is out of range for month

它可以识别多种格式的日期:

In [20]: dparser.parse("monkey 20/01/1980 love banana",fuzzy=True)
Out[20]: datetime.datetime(1980, 1, 20, 0, 0)

请注意,它会猜测日期是否不明确:

In [23]: dparser.parse("monkey 10/01/1980 love banana",fuzzy=True)
Out[23]: datetime.datetime(1980, 10, 1, 0, 0)

但是它解析不明确日期的方式是可定制的:

In [21]: dparser.parse("monkey 10/01/1980 love banana",fuzzy=True, dayfirst=True)
Out[21]: datetime.datetime(1980, 1, 10, 0, 0)

3
@Hamish:如果有两个日期(例如"monkey 10/01/1980 love 7/10/2010 banana"),则可能会引发ValueError;或者(例如"monkey 10/01/1980 love 2010-07-10 banana"),可能会误解第二个日期,表示小时,分钟,秒或时区。fuzzy=True给它猜测的许可证。
unutbu

1
@unutbu海峡=“通过flufie A·2010年10月14日,在下午11点22分A·26篇”通过使用dateutil我得到“ValueError异常:小时必须在0..23”
saravanan

如果文本中有多个日期,该怎么办?
阿尔瓦斯

1
@alvas:该parse函数可能会引发一个异常(即使fuzzy=True),或者使用fuzzy=True,它可能会返回第一个日期或由两个日期的一部分组成的混搭。因此,实际上,parse只应在包含一个日期的字符串上调用。
Unutbu 2015年

1
@Kailegh:是的,可以使用Fuzzy_with_tokens = True推导索引。如果您想进一步澄清,请再提出一个新问题。
unutbu

26

用于从Python中的字符串中提取日期;最好的模块是日期查找器模块。

您可以按照以下简单步骤在Python项目中使用它。

步骤1:安装Datefinder套件

pip install datefinder

步骤2:在项目中使用它

import datefinder

input_string = "monkey 2010-07-10 love banana"
# a generator will be returned by the datefinder module. I'm typecasting it to a list. Please read the note of caution provided at the bottom.
matches = list(datefinder.find_dates(input_string))

if len(matches) > 0:
    # date returned will be a datetime.datetime object. here we are only using the first match.
    date = matches[0]
    print date
else:
    print 'No dates found'

注意:如果您希望进行大量比赛;那么建议不要使用类型转换到列表,因为这会带来很大的性能开销。


1
我发现datefinder传递模糊的日期比python-dateutil从随机的medium.com博客帖子中只返回两个可能的日期要好,而不是五个。不确定如何处理不同的语言环境...
CpILL

这非常好,但是在日期字符串之前有一个冒号(:)时,它由于某种原因不起作用: string = "Assessment Date: 17-May-2017 at 13:31" list(datefinder.find_dates(string.lower())) #[] string = "Assessment Date 17-May-2017 at 13:31" list(datefinder.find_dates(string.lower())) #[datetime.datetime(2017, 5, 17, 13, 31)]
Narahari BM

同意datefinder是堆优于dateparser为复杂的文字
杰伊荣格

2

使用Pygrok,您可以定义正则表达式语法的抽象扩展。

自定义模式可以以格式包含在您的正则表达式中%{PATTERN_NAME}

您也可以通过用冒号分隔来为该模式创建标签:%s{PATTERN_NAME:matched_string}。如果模式匹配,则该值将作为结果字典的一部分返回(例如result.get('matched_string')

例如:

from pygrok import Grok

input_string = 'monkey 2010-07-10 love banana'
date_pattern = '%{YEAR:year}-%{MONTHNUM:month}-%{MONTHDAY:day}'

grok = Grok(date_pattern)
print(grok.match(input_string))

结果值将是一个字典:

{'month': '07', 'day': '10', 'year': '2010'}

如果date_pattern在input_string中不存在,则返回值为None。相反,如果您的模式没有任何标签,它将返回一个空字典{}

参考文献:


1

您还可以尝试使用dateparser模块,该模块可能比自由文本上的datefinder慢,但应该涵盖更多潜在的情况和日期格式,以及大量的语言。


-5

如果您知道日期对象在字符串中的位置(例如,在日志文件中),则可以使用.split()[index]提取日期,而无需完全了解格式。

例如:

>>> string = 'monkey 2010-07-10 love banana'
>>> date = string.split()[1]
>>> date
'2010-07-10'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.