如何将YouTube API持续时间转换为秒?

Mor*_*lde 13 python youtube-api

为了感兴趣,我想将视频持续时间从YouTubes转换ISO 8601为秒.为了将来证明我的解决方案,我选择了一个非常长的视频来测试它.

API提供此期限 - "duration": "P1W2DT6H21M32S"

我尝试使用stackoverflow.com/questions/969285中的dateutil建议解析此持续时间.

import dateutil.parser
duration = = dateutil.parser.parse('P1W2DT6H21M32S')
Run Code Online (Sandbox Code Playgroud)

这引发了一个例外

TypeError: unsupported operand type(s) for +=: 'NoneType' and 'int'
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

jlm*_*ald 21

Python的内置dateutil模块仅支持解析ISO 8601日期,而不支持ISO 8601持续时间.为此,您可以使用"isodate"库(在https://pypi.python.org/pypi/isodate中的pypi中- 通过pip或easy_install安装).该库完全支持ISO 8601持续时间,将它们转换为datetime.timedelta对象.所以一旦你导入了库,它就像下面这样简单:

dur=isodate.parse_duration('P1W2DT6H21M32S')
print dur.total_seconds()
Run Code Online (Sandbox Code Playgroud)

  • @MorganWilde python 的一大优点是,你通常可以找到现有的解决方案,如果不在标准库中,那么可以在 pypi 上找到。如果解决方案已经存在(以任何语言,而不仅仅是 python),最好尝试避免实现任何内容。 (2认同)

sta*_*eng 6

适用于python 2.7+.这里是针对Youtube v3问题JavaScript单行代码.

import re

def YTDurationToSeconds(duration):
  match = re.match('PT(\d+H)?(\d+M)?(\d+S)?', duration).groups()
  hours = _js_parseInt(match[0]) if match[0] else 0
  minutes = _js_parseInt(match[1]) if match[1] else 0
  seconds = _js_parseInt(match[2]) if match[2] else 0
  return hours * 3600 + minutes * 60 + seconds

# js-like parseInt
# https://gist.github.com/douglasmiranda/2174255
def _js_parseInt(string):
    return int(''.join([x for x in string if x.isdigit()]))

# example output 
YTDurationToSeconds(u'PT15M33S')
# 933
Run Code Online (Sandbox Code Playgroud)

处理iso8061持续时间格式以扩展Youtube使用长达数小时


Pet*_*r F 6

这是我的答案,它需要9000的正则表达式解决方案(谢谢 - 对正则表达式的惊人掌握!)并完成了原始海报的 YouTube 用例的工作,即将小时、分钟和秒转换为秒。我使用了.groups()而不是.groupdict(),然后是几个精心构建的列表推导式。

import re

def yt_time(duration="P1W2DT6H21M32S"):
    """
    Converts YouTube duration (ISO 8061)
    into Seconds

    see http://en.wikipedia.org/wiki/ISO_8601#Durations
    """
    ISO_8601 = re.compile(
        'P'   # designates a period
        '(?:(?P<years>\d+)Y)?'   # years
        '(?:(?P<months>\d+)M)?'  # months
        '(?:(?P<weeks>\d+)W)?'   # weeks
        '(?:(?P<days>\d+)D)?'    # days
        '(?:T' # time part must begin with a T
        '(?:(?P<hours>\d+)H)?'   # hours
        '(?:(?P<minutes>\d+)M)?' # minutes
        '(?:(?P<seconds>\d+)S)?' # seconds
        ')?')   # end of time part
    # Convert regex matches into a short list of time units
    units = list(ISO_8601.match(duration).groups()[-3:])
    # Put list in ascending order & remove 'None' types
    units = list(reversed([int(x) if x != None else 0 for x in units]))
    # Do the maths
    return sum([x*60**units.index(x) for x in units])
Run Code Online (Sandbox Code Playgroud)

很抱歉没有发布更高的帖子 - 这里仍然是新的,没有足够的声望点来添加评论。


900*_*000 5

视频不是1周2天6小时21分32秒长吗?

Youtube显示为222小时21分17秒;1 * 7 * 24 + 2 * 24 + 6 = 222。不过,我不知道 17 秒与 32 秒的差异从何而来;也可能是舍入误差。

在我看来,为此编写一个解析器并不难。不幸的是dateutil,似乎没有解析间隔,只有日期时间点。

更新:

我看到有一个用于此目的的包,但作为正则表达式的强大功能、简洁性和难以理解的语法的示例,这里有一个解析器:

import re

# see http://en.wikipedia.org/wiki/ISO_8601#Durations
ISO_8601_period_rx = re.compile(
    'P'   # designates a period
    '(?:(?P<years>\d+)Y)?'   # years
    '(?:(?P<months>\d+)M)?'  # months
    '(?:(?P<weeks>\d+)W)?'   # weeks
    '(?:(?P<days>\d+)D)?'    # days
    '(?:T' # time part must begin with a T
    '(?:(?P<hours>\d+)H)?'   # hourss
    '(?:(?P<minutes>\d+)M)?' # minutes
    '(?:(?P<seconds>\d+)S)?' # seconds
    ')?'   # end of time part
)


from pprint import pprint
pprint(ISO_8601_period_rx.match('P1W2DT6H21M32S').groupdict())

# {'days': '2',
#  'hours': '6',
#  'minutes': '21',
#  'months': None,
#  'seconds': '32',
#  'weeks': '1',
#  'years': None}
Run Code Online (Sandbox Code Playgroud)

我故意不根据这些数据计算确切的秒数。它看起来微不足道(见上文),但实际上并非如此。例如,从 1 月 1 日起 2 个月的距离为 58 天 (30+28) 或 59 天 (30+29),具体取决于年份,而从 3 月 1 日起总是 61 天。正确的日历实施应该考虑到所有这些;对于 YouTube 剪辑长度计算,它一定是过大的。