话痨司机啊 发表于 2022-8-11 01:02

用Python实现类似IDM部分功能

本帖最后由 话痨司机啊 于 2022-8-19 10:51 编辑

参考 @hecoter m3u8的一些源码,实现类似多线程IDM下载的功能,默认16个线程。


from concurrent.futures import ThreadPoolExecutor, as_completed
import requests
from itertools import tee
from alive_progress import alive_bar

def pairwise(iterable):
    '''转换'''
    # pairwise('ABCDEFG') --> AB BC CD DE EF FG
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

def calc_divisional_range(res,threads_count):
    '''分区下载'''
    capacity = int(res.headers['Content-Length'])
    remainder = int(capacity%threads_count)
    singular = int((capacity - remainder)/threads_count)
    url_range = list(pairwise((range(0,capacity - remainder,singular))))
    url_range[-1] = (url_range[-1],capacity -1)
    return url_range

def range_download(url,save_name, s_pos, e_pos,proxies=None):
    '''下载函数'''
    headers = {"Range": f"bytes={s_pos}-{e_pos}"}
    res = requests.get(url, headers=headers, stream=True,proxies=proxies)
    with open(save_name, "rb+") as f:
      f.seek(s_pos)
      for chunk in res.iter_content(chunk_size=64*1024):
            if chunk:
                f.write(chunk)

def download(url,thread_count,save_name=None,proxies=None):
    '''多线程调用下载'''
    # url,thread_count = 'http://yue.cmvideo.cn:8080/depository_yqv/asset/zhengshi/5102/598/709/5102598709/media/5102598709_5010999563_56.mp4',16
    if save_name is None:
      save_name = url.split('/')[-1]
    print(save_name,'下载中……')
    res = requests.head(url,proxies=proxies)
    divisional_ranges = calc_divisional_range(res,thread_count)
    with open(save_name, "wb") as f:
      pass
    with ThreadPoolExecutor(max_workers=thread_count) as p,alive_bar(len(divisional_ranges)+1) as bar:
      futures = []
      for s_pos, e_pos in divisional_ranges:
            # print(s_pos, e_pos)
            futures.append(p.submit(range_download,url,save_name, s_pos, e_pos,proxies=proxies))
      # 等待所有任务执行完毕
      for f in as_completed(futures):
            if f.done():
                bar()
    print(save_name,'下载完成!')

if __name__ == '__main__':
    url = input('输入下载链接:')
    thread_count = 16
    download(url,thread_count)

狂野粗汉子 发表于 2022-8-11 01:13

感谢分享!

吾更爱你 发表于 2022-8-11 07:50

请教下 有两类下载如何用python实现

1、m3u8直播链接 比如b站部分直播用m3u8直播下载器能下载
2、非m3u8直播链接 如视频号 直接用idm就能下载

43991258 发表于 2022-8-11 08:05

谢谢大佬分享

话痨司机啊 发表于 2022-8-11 08:30

本帖最后由 话痨司机啊 于 2022-8-11 08:32 编辑

吾更爱你 发表于 2022-8-11 07:50
请教下 有两类下载如何用python实现

1、m3u8直播链接 比如b站部分直播用m3u8直播下载器能下载

具体你可以请教 hecoter 这位大佬~,我这个只是下载MP4或者单文件的,主要跟解密函数做耦合。m3u8类型跟这个差不多,只是需要解析m3u8并合并多ts.还涉及m 3u8的解密等等。

ErXing 发表于 2022-8-11 08:37

感谢分享

bodongle1 发表于 2022-8-11 09:41

谢谢楼主分享

riyuexiaoyao 发表于 2022-8-11 09:43

感谢大佬分享

忧郁之子 发表于 2022-8-12 16:13

很不错,支持一下。

virsnow 发表于 2022-10-3 12:30

666,学到了
页: [1]
查看完整版本: 用Python实现类似IDM部分功能