import requests
import os
from tqdm import tqdm # 用于显示下载进度条
def download_douyin_video(video_url, output_filename="douyin_video.mp4"):
"""
下载抖音视频,通过模拟浏览器User-Agent和Referer头绕过检查。
Args:
video_url (str): 抖音视频的CDN链接。
output_filename (str): 保存视频的文件名。
"""
# 模拟一个常见的浏览器User-Agent
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36',
# 这是关键!模拟请求来源,告诉服务器请求来自抖音的网站。
# 你可以尝试 https://www.douyin.com/ 或者包含该视频的具体的抖音页面URL
'Referer': 'https://www.douyin.com/',
'Accept': 'video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7',
'Connection': 'keep-alive',
}
print(f"尝试下载视频从: {video_url}")
print(f"保存到文件: {output_filename}")
print("正在使用的请求头:")
for key, value in headers.items():
print(f" {key}: {value}")
try:
# 使用 stream=True 启用内容流式传输,以处理大型文件
# 添加 timeout 防止请求挂起
response = requests.get(video_url, headers=headers, stream=True, timeout=30)
response.raise_for_status() # 检查HTTP请求是否成功 (2xx状态码)
# 获取文件总大小,用于进度条
total_size = int(response.headers.get('content-length', 0))
block_size = 8192 # 8KB per chunk
if total_size == 0:
print("警告: 无法获取文件大小,将不显示进度条。")
# 使用 tqdm 显示下载进度
with open(output_filename, 'wb') as file, tqdm(
total=total_size, unit='B', unit_scale=True, desc=output_filename,
disable=total_size==0 # 如果无法获取总大小,则禁用进度条
) as pbar:
for data in response.iter_content(chunk_size=block_size):
file.write(data)
pbar.update(len(data))
print(f"\n视频下载成功!文件已保存为: {output_filename}")
except requests.exceptions.RequestException as e:
print(f"\n下载失败:请求错误 - {e}")
if "403" in str(e):
print("这通常表示服务器拒绝了您的请求。请尝试以下步骤:")
print("1. **获取最新链接:** 抖音的CDN链接有时效性,旧链接会失效。请在浏览器中打开该抖音视频页面,然后使用开发者工具(F12)的'网络'(Network)标签页,找到真实的视频文件URL(通常是.mp4或tos-cn开头),复制**最新**的URL替换到代码中。")
print(" 操作步骤:")
print(" a. 在浏览器中打开抖音视频页面。")
print(" b. 按 F12 打开开发者工具。")
print(" c. 切换到 'Network' (网络) 标签页。")
print(" d. 播放视频,同时观察网络请求。")
print(" e. 在过滤框中输入 '.mp4' 或 'tos-cn' 进行过滤,找到视频文件的请求。")
print(" f. 右键点击该请求,选择 'Copy' (复制) -> 'Copy link address' (复制链接地址)。")
print(" g. 将复制到的最新链接替换掉 `video_link` 变量的值。")
print("2. **尝试不同的Referer:** 如果仍然失败,可以尝试将 `Referer` 设置为该视频所在的具体抖音页面URL。")
print("3. **检查网络:** 确保您的网络环境没有被限制访问抖音的服务。")
else:
print("请检查URL是否有效,或网络连接是否正常。")
except Exception as e:
print(f"\n下载过程中发生未知错误:{e}")
# 请将您的视频链接替换到这里
# **非常重要:请尝试获取一个最新的、刚刚从浏览器开发者工具中复制的链接!**
video_link = "https://v3-web.douyinvod.com/163a2a20b3ca8e3135bd245b090aa88e/685e28c0/video/tos/cn/tos-cn-ve-15/osyQPzPkADlWACz3fWF6gLIE9AghgbsfAHBom8/?a=6383&ch=26&cr=3&dr=0&lr=all&cd=0%7C0%7C0%7C3&cv=1&br=1564&bt=1564&cs=2&ft=pEaFx4hZffPdOW~-N12NvAq-antLjrKcFbzCRkalhWeVvjVhWL6&mime_type=video_mp4&qs=15&rc=OTdmZ2hnOTNoZ2VlOGU6PEBpajo0bmo5cnV2NDMzNGkzM0BfNTQ2NjIwNjMxNl9hY2M1YSNpZ2RgMmQ0MmFhLS1kLS9zcw%3D%3D&btag=80000e00010000&cquery=100w_100B_100x_100z_100o&dy_q=1750990461&feature_id=10cf95ef75b4f3e7eac623e4ea0ea691&l=20250627101421A2E5A57DC1F6618624B1&__vid=7519819188908510514"
if __name__ == "__main__":
download_douyin_video(video_link, "我的抖音视频.mp4")