如何不用客户端下载 YouKu 视频-YouKu 实现下载 Python3 实现

有时候发现Youku上有比较好的视频,想下载,要是使用 Windows 可以使用其客户端。要是使用非 Windows系统,没有客户端可以用,就需要自己想办法。这里是分析了 Youku 的协议之后的,使用 Python 实现的下载工具.

# !/usr/bin/env python3# encoding: utf-8__author__ = 'PiZhong Zhou (zpz@zpz.me)'from sys import argvfrom re import compilefrom os import mkdirfrom os.path import isfile, join, dirname, exists, basenamefrom urllib.parse import quotefrom urllib.request import urlopenfrom json import loadsfrom base64 import decodebytes, encodebytes_re_url_id = compile('id_(\w+)\.')_magic_1 = b'becaf9be'_magic_2 = b'bf7e5f01'_info_url = 'http://v.youku.com/player/getPlayList/' \            'VideoIDS/%s/Pf/4/ctype/12/ev/1'_m3u8_url = 'http://pl.youku.com/playlist/m3u8?' \            'ctype=12&ep=%s&ev=1&keyframe=1&oip=%s&' \            'sid=%s&token=%s&type=%s&vid=%s'_save_base_dir = dirname(__file__)_default_types = (    'hd3',  # 1080P    'dh2',  # 超清    'mp4', '3gphd', 'flvhd',  # 高清    'flv'  # 标清)def _encode(magic, s):    f = 0    r = []    m = [i for i in range(256)]    for i in range(256):        f = (f + m[i] + magic[i % len(magic)]) % 256        m[i], m[f] = m[f], m[i]    f = i = 0    for c in s:        i = (i + 1) % 256        f = (f + m[i]) % 256        m[i], m[f] = m[f], m[i]        r.append(c ^ m[(m[i] + m[f]) % 256])    return bytes(r)def get_youku_video(url_or_id, types=None):    assert url_or_id, ValueError('require a you video url or id')    if url_or_id.find('id_') > -1:        m = _re_url_id.search(url_or_id)        assert m, ValueError('No id contains in url')        url_or_id = m.group(1)    if isinstance(types, str):        types = [types]    elif not types:        types = _default_types    assert isinstance(types, (list, tuple)), \        ValueError('prefers must be a str or list of str or None')    print('> Get basic info of :', url_or_id)    data = urlopen(_info_url % url_or_id).read()    info = loads(data.decode('utf-8'))    info = info['data'][0]    video_name = info['title']    print('> Video name :', video_name)    print('> Video publisher :', info['username'])    types = info['segs'].keys()    video_type = None    for t in types:        if t in types:            video_type = t            break    assert video_type, ValueError('Only "%s" formats are available.' % (', '.join(types)))    print('> Choose video type "%s"' % video_type)    sid, token = _encode(_magic_1, decodebytes(info['ep'].encode())).split(b'_', 1)    ep = quote(encodebytes(_encode(_magic_2, sid + b'_' + url_or_id.encode() + b'_' + token))[:-1])    token = token.decode()    sid = sid.decode()    print('> Retrieve file list')    url_list = set()    for line in urlopen(_m3u8_url % (ep, info['ip'], sid, token, video_type, url_or_id)).read().splitlines():        line = line.strip()        if line.startswith(b'#'):            continue        i = line.find(b'?')        if i > -1:            line = line[:i]            url_list.add(line.decode())    _save_dir = join(_save_base_dir, video_name.replace(' ', '__'))    exists(_save_dir) or mkdir(_save_dir)    print('> %s file(s) to retrieve' % len(url_list))    for i, url in enumerate(url_list):        filename = '%d.%s' % (i, url[url.rfind('.') + 1:])        save_path = join(_save_dir, filename)        print('---- ' + filename)        if isfile(save_path):            print('---- Fetched, Skip')            continue        data = urlopen(url).read()        print('---- Size :', len(data))        with open(save_path, 'wb') as f:            f.write(data)        del data    print('> Done')if __name__ == '__main__':    if len(argv) < 2:        print('''Usage:python3 %(s)s "youku video url or video id"python3 %(s)s XNjkwODQ4NTk2''' % {'s': basename(argv[0])})        exit()    for v in argv[1:]:        get_youku_video(v)

示例,下载《神盾局特工 2》第二集

如何不用客户端下载 YouKu 视频-YouKu 实现下载 Python3 实现

相关文章:

你感兴趣的文章:

标签云: