Python正则表达式匹配一段文本中的日期

4
如何通过Python从文本文件中找到尽可能多的日期模式?日期模式的定义如下:
dd mmm yyyy
  ^   ^
  |   |
  +---+--- spaces

在哪里:
  • dd是两位数数字
  • mmm是三个字母的英文月份名称(例如:Jan、Mar、Dec)
  • yyyy是四位数年份
  • 有两个空格作为分隔符
谢谢!

我不明白你的意思。你是想要使用grep查找日期模式,还是按照固定的单一模式查找日期? - wilhelmtell
我想提取实际日期。 - ohho
5个回答

11

这是一种找到与您的模式匹配的所有日期的方法

re.findall(r'\d\d\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}', text)

但在WilhelmTell对你的问题的评论之后,我也在想这是否是你真正想要问的……


9
使用日历模块可以让您具备一些全球意识:
date_expr = r"\d{2} (?:%s) \d{4}" % '|'.join(calendar.month_abbr[1:])
print date_expr
print re.findall(date_expr, source_text)

对我来说,这会创建一个类似于date_expr的日期表达式:
"\d{2} (:?Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4}"

但是,如果我使用locale模块更改我的区域设置:
locale.setlocale(0, "fr")

我现在在法国搜索了好几个月:

"\d{2} (?:janv.|févr.|mars|avr.|mai|juin|juil.|août|sept.|oct.|nov.|déc.) \d{4}"

嗯,这是我第一次尝试使用法语月份缩写,我可能需要进行一些清理:

date_expr = r"\d{2} (?:%s) \d{4}" % '|'.join(
    m.title().rstrip('.') for m in calendar.month_abbr[1:])

现在我明白了:
"\d{2} (?:Janv|Févr|Mars|Avr|Mai|Juin|Juil|Août|Sept|Oct|Nov|Déc) \d{4}"

现在我的脚本也可以为我的高卢朋友运行,而且非常容易。

(你可能会想为什么我必须从[1:]中切割month_abbr列表 - 这个列表在位置0处以空字符串开头,因此如果您使用find()查找特定月份的缩写,则将返回1-12之间的数字,而不是0-11之间的数字。)

-- Paul


这就是为什么我更喜欢使用 RE 来验证基本格式(_day month-abbrev year_),然后让 strptime 处理月份的本地化。如果你真的感兴趣,也可以使用一些区域设置感知选项来考虑 M-D-Y 排序上的差异。 - D.Shawley

5

这里是一个稍微完整一些的例子。正则表达式将匹配不仅仅是有效的日期值。datetime.strptime无法解析任何非有效日期,会抛出ValueError异常。如果日期被解析,则您将拥有一个完整的datetime对象,该对象提供了许多功能。

>>> from datetime import datetime
>>> import re
>>> dates = []
>>> patn = re.compile(r'\d{2} \w{3} \d{4}')
>>> fh = open('inputfile')
>>> for line in fh:
...   for match in patn.findall(line):
...     try:
...       val = datetime.strptime(match, '%d %b %Y')
...       dates.append(val)
...     except ValueError:
...       pass # ignore, this isn't a date
...

我想如果你愿意,这段代码可以通过使用综合语句来压缩成更紧凑的形式。

非常感谢!我应该如何在Python中将“val”连接到数组中? - ohho

0

或者你可以完全使用这个

date = re.findall(r'\d\d\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}', text)
print date
['30 November 2010 14:20', '30 November 2010 14:24']

0

试试这个:

import re

allmatches = re.findall(r'\d\d \w\w\w \d\d\d\d', "string to match")

2
认真的吗?-1?除了'\w\w\w'之外还有其他原因不太适合匹配月份吗?这确实是那个人在他的'dd mmm yyyy'语法中要求的。虽然这并不是理想的方法,但我不明白为什么会被踩。 - dlamotte
嗨,虽然很晚了,但可以给出任意三个字母数字字符吗?它们可以是非常随机的吗?如果我错了,请纠正我。 - Shivaraj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接