最近在做一个视频分析项目,需要批量下载AcFun上的视频素材。网上现成的下载工具要么收费,要么功能不全,还经常失效。于是决定自己用Python开发一个,顺便记录下实现过程和技术要点。

为什么需要自己开发下载工具?

现有的AcFun视频下载方案主要有两种:

  • 在线解析网站:不稳定,经常被屏蔽,而且有视频清晰度限制
  • 浏览器插件:功能单一,无法批量处理,缺乏定制化能力

对于开发者来说,这些方案都无法满足自动化、批量化处理的需求。自己开发工具可以灵活控制下载逻辑,还能集成到其他系统中。

视频下载示意图

技术原理分析

1. 视频源获取机制

通过浏览器开发者工具分析,发现AcFun的视频播放是通过调用内部API获取视频源地址的。关键API接口是:

https://www.acfun.cn/rest/pc-direct/video/getPlayInfo

这个接口需要携带以下关键参数:

  • videoId:视频唯一标识
  • resourceType:资源类型(通常为2)
  • platform:平台标识(pc端为1)

2. 参数加密逻辑

接口请求需要携带签名参数sign,这个签名是通过以下方式生成的:

  1. 将所有参数按字典序排序
  2. 拼接成key=value&格式的字符串
  3. 加上一个固定盐值
  4. 进行MD5哈希

Python实现方案

基础环境准备

需要安装以下Python库:

pip install requests tqdm

核心代码实现

1. 获取视频信息

import hashlib
import time
import requests

def get_video_info(video_id):
    base_url = 'https://www.acfun.cn/rest/pc-direct/video/getPlayInfo'
    params = {
        'videoId': video_id,
        'resourceType': 2,
        'platform': 1,
        'timestamp': int(time.time() * 1000)
    }

    # 生成签名
    sign_str = '&'.join([f'{k}={v}' for k,v in sorted(params.items())]) + 'your_salt_value'
    sign = hashlib.md5(sign_str.encode()).hexdigest()
    params['sign'] = sign

    response = requests.get(base_url, params=params)
    if response.status_code == 200:
        return response.json()
    return None

2. 下载视频实现

from tqdm import tqdm

def download_video(url, save_path):
    response = requests.get(url, stream=True)
    total_size = int(response.headers.get('content-length', 0))

    with open(save_path, 'wb') as f, tqdm(
        desc=save_path,
        total=total_size,
        unit='iB',
        unit_scale=True,
        unit_divisor=1024,
    ) as bar:
        for data in response.iter_content(chunk_size=1024):
            size = f.write(data)
            bar.update(size)

下载进度显示

避坑指南

1. 反爬机制应对

AcFun有以下反爬措施:

  • 请求频率限制:建议在每个请求间加入随机延迟
  • User-Agent检测:需要设置合理的浏览器UA
  • IP封锁:建议使用代理IP池

2. 大文件下载优化

  • 使用stream=True参数避免内存溢出
  • 合理设置chunk_size(1024或2048)
  • 支持断点续传

3. 网络异常处理

def safe_download(url, save_path, max_retry=3):
    for i in range(max_retry):
        try:
            download_video(url, save_path)
            return True
        except Exception as e:
            print(f'下载失败,重试 {i+1}/{max_retry}: {e}')
            time.sleep(2)
    return False

合规说明

本工具仅限个人学习使用,请遵守AcFun的用户协议:

  • 不得用于商业用途
  • 不得批量下载造成服务器压力
  • 尊重视频版权

扩展思考

这个基础版本还可以进一步优化:

  1. 批量下载功能:读取视频ID列表自动下载
  2. 自动转码:下载后自动转为MP4格式
  3. 图形界面:使用PyQt或Tkinter开发可视化界面
  4. 跨平台支持:打包为exe或mac应用

完整项目代码已放在GitHub上,有需要的朋友可以自行扩展。记住技术是把双刃剑,要用在正道上!

Logo

音视频技术社区,一个全球开发者共同探讨、分享、学习音视频技术的平台,加入我们,与全球开发者一起创造更加优秀的音视频产品!

更多推荐