【问题标题】:Error while parsing date when input has non-date numeric values当输入具有非日期数值时解析日期时出错
【发布时间】:2017-07-22 05:01:39
【问题描述】:

我正在从具有其他类似日期格式的 pdf 文档中解析日期

Traceback (most recent call last):
  File "/Users/akjain/Documents/workspace/Parse13F/13FParser.py", line 26, in <module>
    print dparser.parse('  Crl. A. Nos. 291/16, 300/16, 581/16 & 1143/16 Judgment reserved on :   May 31, 2017  ', fuzzy=True)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/dateutil/parser.py", line 697, in parse
    return DEFAULTPARSER.parse(timestr, **kwargs)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/dateutil/parser.py", line 303, in parse
    raise ValueError, "unknown string format"
ValueError: unknown string format

我的输入是

print dparser.parse('  Crl. A. Nos. 291/16, 300/16, 581/16 & 1143/16 Judgment reserved on :   May 31, 2017  ', fuzzy=True)

如果我从字符串中删除“291/16、300/16、581/16 和 1143/16”,代码运行完美。

任何人都可以在忽略上述值的同时帮助我解析日期。

【问题讨论】:

  • print 语句的结果应该是什么?
  • 要亲自回复我,请输入“at”符号以获取收件人菜单,选择我的姓名,然后输入您的回复。

标签: python python-2.7 parsing python-dateutil datetime-parsing


【解决方案1】:

这可能是因为库在字符串中看到了多个类似日期的组件而感到困惑。如果您知道您的日期看起来像 May 31, 2017 并且误报看起来像 581/16,您可以在执行模糊解析之前将正则表达式应用于字符串以清理它:

import re

string = '  Crl. A. Nos. 291/16, 300/16, 581/16 & 1143/16 Judgment reserved on :   May 31, 2017  '
string = re.sub('[\d]+/[\d]+', '', s)
print dparser.parse(string, fuzzy=True)

如果您想定义要解析的日期的结构,则可以以不同的方式使用正则表达式:

import re

s = 'test 234/23/134 234 291/16, 300/16, 581/16 & 1143/16 May 31, 2017 10/15/1997'
match_1 = re.search(r'[A-Za-z]+ [\d]{1,2}, [\d]{4}', s)
print match_1.group(0)
# => May 31, 2017
match_2 = re.search(r'[\d]{2}/[\d]{2}/[\d]{4}', s)
print match_2.group(0)
# => 10/15/1997

您甚至可以将两者结合起来,提取在给定行中显示的所有日期,以符合您的预期模式:

import re

pattern_1 = r'[A-Za-z]+ [\d]{1,2}, [\d]{4}'
pattern_2 = r'[\d]{2}/[\d]{2}/[\d]{4}'
matches = re.findall(r'{}|{}'.format(pattern_1, pattern_2), s)
print matches
# => ['May 31, 2017', '10/15/1997']

【讨论】:

  • 谢谢 danielcorin... 这当然有帮助...但是,另一个挑战是我的文档还有很多其他数字也采用以下格式:234/23/134 或 234。现在提交这些两种格式也可能过滤格式 23/12/2017 的日期......那么,有没有一种方法可以让我定义我的日期可能是什么样子,而不是过滤非日期的数据
  • 可以,也可以使用正则表达式。查看上面的修改
  • 这绝对是正在发生的事情。
【解决方案2】:

使用带有except 子句的try 语句,例如:

try:
    print dparser.parse('...')
except ValueError as ve:
    print('ValueError: {}'.format(ve))

【讨论】:

    【解决方案3】:

    由于您知道哪种日期格式适用于该解析器,您可以使用基于正则表达式的代码将其他日期格式转换为该格式,并删除混淆解析器的项目。

    在这个解释性示例中,我在您正在使用的字符串的开头附近添加了日期“23/12/2017”。此代码监视re.sub 中指示的模式并将匹配的字符串传递给processprocess 删除任何由少于三个部分组成的部分。然后它会尝试从匹配中的三个数字中创建一个日期,它已经通过。如果成功,那么它将按照输出中的指示格式化该日期,以便解析器能够识别它。我已经将箭头库与 datetime 一起用于这些日期操作。

    >>> import re
    >>> s = 'On 23/12/2017  Crl. A. Nos. 291/16, 300/16, 581/16 & 1143/16 Judgment reserved on :   May 31, 2017  '
    >>> from datetime import datetime
    >>> import arrow
    >>> def process(matchobj):
    ...     items = matchobj.group(0).split('/')[::-1]
    ...     items = [int(_) for _ in items]
    ...     if len(items)<3:
    ...         return ''
    ...     try:
    ...         the_date = arrow.get(datetime(*items))
    ...         return the_date.format('MMMM DD, YYYY')
    ...     except:
    ...         return matchobj.group(0)
    ... 
    >>> re.sub(r'(?:\d+/)+\d+', process, s)
    'On December 23, 2017  Crl. A. Nos. , ,  &  Judgment reserved on :   May 31, 2017  '
    

    【讨论】:

      猜你喜欢
      • 2021-06-29
      • 1970-01-01
      • 2018-04-18
      • 2014-06-13
      • 2017-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多