文档章节

批量下载字幕

quminzi
 quminzi
发布于 2017/07/26 12:20
字数 525
阅读 18
收藏 0

需求:下载大量英文字幕

站点: subsmax.com

关键: 主要靠 http proxy 越过下载限制(24个字幕/小时)。另外,尝试多线程加速(对于io密集任务)。requets session 复用 http 连接减轻 http 延迟。

 

import io
import logging
import os
import threading
import time
import zipfile
from queue import Queue

import requests
from freeproxy import (fetch_proxies, from_cn_proxy, init_db, read_proxies,
                       test_proxies, enable_logging)

log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
if not log.handlers:
    stream = logging.StreamHandler()
    stream.setFormatter(logging.Formatter(
        fmt='[%(levelname)-5s] %(asctime)s %(threadName)s: %(message)s'))
    log.addHandler(stream)


# enable_logging()


class MyProxy(object):
    TEST_URL = 'http://subsmax.com/'

    def __init__(self, test_url=None, load_from_db=True):
        if test_url:
            self.test_url = test_url
        else:
            self.test_url = self.TEST_URL
        init_db()
        self.proxies = set()
        if load_from_db:
            self.proxies.update(read_proxies())  # init from db
        log.debug('loaded %d proxies' % len(self.proxies))

    def fetch(self):
        # return fetch_proxies()
        return from_cn_proxy()

    def test(self, proxies):
        return test_proxies(proxies, timeout=5, single_url=self.test_url)

    def update(self):
        log.debug('updating proxies ...')
        # ret = subprocess.call(['freeproxy', '-l', '-t', self.test_url])
        # self.proxies.extend(read_proxies())
        self.proxies.update(self.test(self.fetch()))
        log.debug('updated %d proxies' % len(self.proxies))
        return self.proxies


def get_proxy():
    # g_lock.acquire()
    # while len(g_proxy.proxies) < TOTAL_THREAD:
    #     g_proxy.update()
    # g_lock.release()
    while not g_proxy.proxies:
        time.sleep(1)
    return g_proxy.proxies.pop()


def change_proxy(session):
    session.proxies.update({'http': get_proxy()})
    log.debug('session changed proxy to %s' % session.proxies)


def get_session():
    s = requests.Session()
    change_proxy(s)
    return s


def load_urls(filename):
    with open(filename) as f:
        for line in f:
            yield line.rstrip()


def is_zipfile(data):
    return zipfile.is_zipfile(io.BytesIO(data))
    # return data[:4] == b'\x50\x4b\x03\x04'  # fast dirty check


def save_zipfile(url, data):
    sub_id = url.rsplit('/', 1)[-1]
    filename = os.path.join(OUT_DIR, sub_id)
    with open(filename, 'wb') as f:
        f.write(data)
    log.info('saved data to %s' % filename)


def download_subtitle(session, url):
    failed = False
    try:
        r = session.get(url, timeout=5)
    except requests.exceptions.RequestException as e:
        log.error('request error: <%s> %s' % (e.__class__.__name__, e))
        failed = True
    else:
        if r.status_code != 200:
            log.warn('response status code: %s' % (r.status_code))
            failed = True
        elif not is_zipfile(r.content):
            log.warn('reponse data not zip-encoding')
            failed = True
    if failed:
        change_proxy(session)
    else:
        save_zipfile(url, r.content)
    return not failed


# def message(s):
#     print('{}: {}'.format(threading.current_thread().name, s))


def download_worker(url_queue):
    session = get_session()
    proxy = session.proxies.get('http')
    q = url_queue
    while 1:
        url = q.get()
        log.debug('proxy={}, url={}'.format(proxy, url))
        if not download_subtitle(session, url):
            q.put(url)
        q.task_done()


def update_proxy_pool():
    log.debug('start')
    check_point = int(TOTAL_THREAD * 1.2)
    while 1:
        g_lock.acquire()
        if len(g_proxy.proxies) <= check_point:
            g_proxy.update()
        g_lock.release()
        time.sleep(60)
    log.debug('end')


def start_proxy_pool():
    proxy_worker = threading.Thread(
        target=update_proxy_pool,
        name='proxy-worker',
    )
    proxy_worker.setDaemon(True)
    proxy_worker.start()


def main():
    jobs = []
    for i in range(TOTAL_THREAD):
        t = threading.Thread(
            group=None,
            target=download_worker,
            name='woker-%d' % i,
            args=(g_url_queue,),
        )
        t.setDaemon(True)
        t.start()
        jobs.append(t)

    log.debug('putting urls in queue ...')
    total_url = 0
    for url in load_urls(LINK_FILENAME):
        g_url_queue.put(url)
        total_url += 1
    log.info('enqueued %d urls' % total_url)

    start_proxy_pool()

    log.debug('waiting url queue to join')
    g_url_queue.join()
    log.debug('all task done')


# def main():
#     urls = load_urls('./en.links')
#     session = get_session()
#     succs = fails = 0
#     for url in urls:
#         if download_subtitle(session, url):
#             succs += 1
#         else:
#             fails += 1
#     log.debug('succs={}, fails={}'.format(succs, fails))


LINK_FILENAME = './todo.links'
OUT_DIR = './episodes'
TOTAL_THREAD = 4
g_proxy = MyProxy(load_from_db=True)
g_url_queue = Queue()
g_lock = threading.Lock()


if __name__ == '__main__':
    main()

 

© 著作权归作者所有

共有 人打赏支持
quminzi
粉丝 0
博文 1
码字总数 525
作品 0
东城
程序员
有正则高手在不,麻烦看看我这个问题如何解决。

现在的情况是这样的。 1、我在微软Microsoft Virtual Academy网站上下载教学视频,视频下载下来后发现没有中文字幕,但是微软的网站上播放时候是有字幕的,通过查看网页源码我把字幕文件下载...

ipenglei
2014/08/03
985
11
视频字幕下载软件--Google2SRT

什么是Google2SRT? Google2SRT可以下载youtube及google 视频非内嵌字幕 (Closed Captions - CC)的软件。并且可以将非内嵌字幕转换成标准字幕格式 (SubRip - SRT)。 当今,youtube的非内嵌字幕...

匿名
2012/10/09
2K
0
Youtube 网站视频和字幕下载

由于工作的需要,我经常要去Youtube网站观看技术相关视频,当遇到好的视频想将视频和字幕下载下来,今天就主要介绍如果去Youtube官网下载相关视频及字幕的方法。 下面列出需要的工具: 安装完...

yelang007sheng
2017/03/18
0
0
对你来说,有这两款视频剪辑工具就足够了

之前做头条号的时候有些朋友咨询,自己也想做头条号,其中有一个问题就是不知道该使用什么剪辑工具来处理视频。 我相信我们中绝大多数人在剪辑视频方面并不是专业人士,比较专业的剪辑工具如...

我是徐老师呀
05/30
0
0
射手影音播放器的网友评论

射手影音播放器是由射手网创建与维护的开源播放器项目。内核基于MPC(感谢Gabest)、MPC-HC与ffmpeg。同时加入更多真正符合中国用户习惯的功能,旨在改进华人的数字影视观赏体验,建立和维护...

红薯
2009/12/11
922
10

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Ubuntu18.04 显卡GF-940MX安装NVIDIA-390.77

解决办法: 下面就给大家一个正确的姿势在Ubuntu上安装Nvidia驱动: (a)首先去N卡官网下载自己显卡对应的驱动:www.geforce.cn/drivers (b)下载后好放在英文路径的目录下,怎么简单怎么来...

AI_SKI
今天
0
0
深夜胡思乱想

魔兽世界 最近魔兽世界出了新版本, 周末两天升到了满级,比之前的版本体验好很多,做任务不用抢怪了,不用组队打怪也是共享拾取的。技能简化了很多,哪个亮按哪个。 运维 服务器 产品 之间的...

Firxiao
今天
0
0
MySQL 8 在 Windows 下安装及使用

MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Windows 下安装 MySQL 8,以及基本的 MySQL 用法。 下载 下载地址 https://dev....

waylau
今天
0
0
微信第三方平台 access_token is invalid or not latest

微信第三方开发平台code换session_key说的特别容易,但是我一使用就带来无穷无尽的烦恼,搞了一整天也无济于事. 现在记录一下解决问题的过程,方便后来人参考. 我遇到的这个问题搜索了整个网络也...

自由的开源
今天
2
0
openJDK之sun.misc.Unsafe类CAS底层实现

注:这篇文章参考了https://www.cnblogs.com/snowater/p/8303698.html 1.sun.misc.Unsafe中CAS方法 在sun.misc.Unsafe中CAS方法如下: compareAndSwapObject(java.lang.Object arg0, long a......

汉斯-冯-拉特
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部