Python dateutil解析器,忽略字符串的非日期部分

时间:2013-06-09 16:33:23

标签: python python-2.7 python-dateutil

我使用dateutil来解析图片文件名并根据日期对它们进行排序。由于并非我的所有图片都有元数据,因此dateutil试图猜测将它们放在哪里。

我的大多数照片都采用以下格式: 2007-09-10_0001.jpg 2007-09-10_0002.jpg 等...

fileName = os.path.splitext(file)[0]
print("Guesssing date from ", fileName)
try:
    dateString = dateParser.parse(file, fuzzy=True)
    print("Guessed date", dateString)
    year=dateString.year
    month = dateString.month
    day=dateString.day
except ValueError:
    print("Unable to determine date of ", file)

我得到的回报是:

('Guesssing date from ', '2007-09-10_00005')
('Unable to determine date of ', '2007-09-10_00005.jpg')

现在我应该能够从下划线之后删除所有内容,但如果可能的话,我想要一个更强大的解决方案,以防我有其他格式的图片。我虽然模糊会尝试在字符串中找到任何日期并与之匹配,但显然不起作用......

是否有一种简单的方法可以让解析器找到看起来像日期的东西并在此之后停止?如果没有,强制解析器忽略下划线后的所有内容的最简单方法是什么?或者使用忽略部分定义多种日期格式的方法。

谢谢!

2 个答案:

答案 0 :(得分:4)

你可以尝试减少"字符串,只要你不能解码它:

from dateutil import parser

def reduce_string(string):
    i = len(string) - 1
    while string[i] >= '0' and string[i] < '9':
        i -= 1
    while string[i] < '0' or string[i] > '9':
        i -= 1
    return string[:i + 1]

def find_date(string):
    while string:
        try:
            dateString = parser.parse(string, fuzzy=True)
            year = dateString.year
            month = dateString.month
            day = dateString.day
            return (year, month, day)
        except ValueError:
            pass

        string = reduce_string(string)

    return None

date = find_date('2007-09-10_00005')
if date:
    print date
else:
    print "can't decode"

想法是删除字符串的结尾(任何数字,然后是任何非数字),直到解析器可以将其解码为有效日期。

答案 1 :(得分:2)

从这里评论未来,更多地了解这个问题。

虽然dateutil的模糊搜索非常擅长以正常的自然语言提取日期,但它会像上面的字符串一样失败,会产生大量的数字/符号相关噪音。但是,在运行时使用更新版本的dateutil

>>> from dateutil.parser import parse
>>> parse('2007-09-10_00005.jpg', fuzzy=True)

parseTypeError: 'NoneType' object is not iterable失败,这不是非常惯用的。

另一种选择是使用正则表达式来寻找已知的日期格式。当然,这根据用例而有所不同,但OP提到他的日期始终采用YYYY-MM-DD格式,这使其成为正则表达式搜索的理想选择:

from dateutil.parser import parse
import re

date_pattern = re.compile('\d{4}-\d{2}-\d{2}')

def extract_date(filename):
    matches = re.match(date_pattern, filename)
    if matches:
        return parse(matches.group(0))
    else:
        return None

extract_date('2007-09-10_00005.jpg')  # datetime.datetime(2007, 9, 10, 0, 0)