【问题标题】:How to use russian date string with strptime如何在 strptime 中使用俄罗斯日期字符串
【发布时间】:2017-06-09 22:19:26
【问题描述】:

我用 python 解析 html 并且有日期字符串:[ 24-Янв-17 07:24 ]。 “Янв”是“简”。我想把它转换成日期时间对象。

# Some beautifulsoup parsing
timeData = data.find('div', {'id' : 'time'}).text

import locale
locale.setlocale(locale.LC_TIME, 'ru_RU.UTF-8')
result = datetime.datetime.strptime(timeData, u'[ %d-%b-%y  %H:%M ]')

错误是:

ValueError: 时间数据 '[ 24-\xd0\xaf\xd0\xbd\xd0\xb2-17 07:24 ]' 确实 不匹配格式 '[ %d-%b-%y %H:%M ]'

type(timeData) 返回 unicode。从utf-8 编码timeData 返回UnicodeEncodeError。怎么了?


chardet 返回{'confidence': 0.87625, 'encoding': 'utf-8'},当我写:datetime.datetime.strptime(timeData.encode('utf-8'), ...) 它返回错误如上。


原始页面有window-1251编码。

print type(timeData)
print timeData


timeData = timeData.encode('cp1251')
print type(timeData)
print timeData

返回

<type 'unicode'>
[ 24-Янв-17 07:24 ]
<type 'str'>
[ 24-???-17 07:24 ]

【问题讨论】:

标签: python encoding


【解决方案1】:

快速修复

知道了! янв 在 CPython 2.7.12 中必须小写。代码(在 cygwin 上的 CPy 2.7.12 和 CPy 3.4.5 中工作):

# coding=utf8
#timeData='[ 24-Янв-17 07:24 ]'
timeData='[ 24-янв-17 07:24 ]'    ### lower-case
import datetime
import locale
locale.setlocale(locale.LC_TIME, 'ru_RU.UTF-8')
result = datetime.datetime.strptime(timeData, u'[ %d-%b-%y  %H:%M ]')
print(result)

结果:

2017-01-24 07:24:00

如果我使用大写的Янв,它在 Py 3 中有效,但在 Py 2 中它给出了

ValueError: time data '[ 24-\xd0\xaf\xd0\xbd\xd0\xb2-17 07:24 ]' does not match format '[ %d-%b-%y  %H:%M ]'

一般情况

要在Python 2 中 处理这个问题,首先要小写(参见this answer):

# coding=utf8
timeData=u'[ 24-Янв-17 07:24 ]'
       # ^ unicode data
import datetime
import locale
locale.setlocale(locale.LC_TIME, 'ru_RU.UTF-8')
print(timeData.lower())     # works OK
result = datetime.datetime.strptime(
    timeData.lower().encode('utf8'), u'[ %d-%b-%y  %H:%M ]')
    ##               ^^^^^^^^^^^^^^ back to a string
    ##       ^^^^^^^ lowercase
print(result)

结果:

[ 24-янв-17 07:24 ]
2017-01-24 07:24:00

我不能用你的 beautifulsoup 代码测试它,但是,一般来说,得到 Unicode 数据,然后使用上面的。

或者,如果可能的话,切换到 Python 3 :)。

说明

那么我是怎么发现的呢?我在 CPython 源代码中查找 strptime (search) 的代码。我找到了方便的_strptime 模块,其中包含class LocaleTime。我还发现了LocaleTime 中的mention。要打印可用的月份名称,请执行以下操作(添加到上面“快速修复”下的代码末尾):

from _strptime import LocaleTime
lt = LocaleTime()
print(lt.a_month)    

a_month 具有每个 the source 的缩写月份名称。

在 Py3 上,产生:

['', 'янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек']
      ^ lowercase!

在 Py2 上,产生:

['', '\xd1\x8f\xd0\xbd\xd0\xb2',

还有更多。请注意,第一个字符是\xd1\x8f,在您的错误消息中,\xd0\xaf 不匹配。

【讨论】:

  • @Ockonal 很高兴能够提供帮助!我学到了一些新东西,我一直很喜欢。 :)
【解决方案2】:

您可以用英文更改俄语月份名称:

ru_to_eng_months = {'Янв': 'Jan', } # fill it with other months

def ru_to_eng_datetime(ru) -> string:
    s = ru.split('-')
    eng_month  = ru_to_eng_months[s[1]]
    return s[0] + '-' + eng_month + '-' + s[2]

s = u'[ 24-Янв-17 07:24 ]'
dateTime = ru_to_eng_datetime(s)
result = datetime.datetime.strptime(dateTime, u'[ %d-%b-%y  %H:%M ]')
print(result) # 2017-01-24 07:24:00

【讨论】:

  • 嘿,更好的是,为什么不直接使用datetime.datetime(2017, 1, 24)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-04
相关资源
最近更新 更多