mirror of
https://github.com/Evil0ctal/Douyin_TikTok_Download_API.git
synced 2025-04-12 03:37:05 +08:00
121 lines
5.5 KiB
Python
121 lines
5.5 KiB
Python
import os
|
|
import zipfile
|
|
|
|
import aiofiles
|
|
import httpx
|
|
import yaml
|
|
from fastapi import APIRouter, Request # 导入FastAPI组件
|
|
from starlette.responses import FileResponse
|
|
|
|
from app.api.models.APIResponseModel import ErrorResponseModel # 导入响应模型
|
|
from crawlers.hybrid.hybrid_crawler import HybridCrawler # 导入混合数据爬虫
|
|
|
|
router = APIRouter()
|
|
HybridCrawler = HybridCrawler()
|
|
|
|
# 读取上级再上级目录的配置文件
|
|
config_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))), 'config.yaml')
|
|
with open(config_path, 'r', encoding='utf-8') as file:
|
|
config = yaml.safe_load(file)
|
|
|
|
|
|
async def fetch_data(url: str):
|
|
headers = {
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
|
}
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.get(url, headers=headers)
|
|
response.raise_for_status() # 确保响应是成功的
|
|
return response
|
|
|
|
|
|
@router.get("/download", summary="在线下载抖音|TikTok视频/图片/Online download Douyin|TikTok video/image")
|
|
async def download_file_hybrid(request: Request,
|
|
url: str, prefix: bool = True, with_watermark: bool = False):
|
|
# 是否开启此端点/Whether to enable this endpoint
|
|
if not config["API"]["Download_Switch"]:
|
|
code = 400
|
|
message = "Download endpoint is disabled."
|
|
return ErrorResponseModel(code=code, message=message, router=request.url.path, params=dict(request.query_params))
|
|
|
|
# 开始解析数据/Start parsing data
|
|
try:
|
|
data = await HybridCrawler.hybrid_parsing_single_video(url, minimal=True)
|
|
except Exception as e:
|
|
code = 400
|
|
return ErrorResponseModel(code=code, message=str(e), router=request.url.path, params=dict(request.query_params))
|
|
|
|
# 开始下载文件/Start downloading files
|
|
try:
|
|
data_type = data.get('type')
|
|
platform = data.get('platform')
|
|
aweme_id = data.get('aweme_id')
|
|
file_prefix = config.get("API").get("Download_File_Prefix") if prefix else ''
|
|
download_path = os.path.join(config.get("API").get("Download_Path"), f"{platform}_{data_type}")
|
|
|
|
# 确保目录存在/Ensure the directory exists
|
|
os.makedirs(download_path, exist_ok=True)
|
|
|
|
# 下载视频文件/Download video file
|
|
if data_type == 'video':
|
|
file_name = f"{file_prefix}{platform}_{aweme_id}.mp4" if not with_watermark else f"{file_prefix}{platform}_{aweme_id}_watermark.mp4"
|
|
url = data.get('video_data').get('nwm_video_url_HQ') if not with_watermark else data.get('video_data').get(
|
|
'wm_video_url_HQ')
|
|
file_path = os.path.join(download_path, file_name)
|
|
|
|
# 判断文件是否存在,存在就直接返回
|
|
if os.path.exists(file_path):
|
|
return FileResponse(path=file_path, media_type='video/mp4', filename=file_name)
|
|
|
|
# 获取视频文件
|
|
response = await fetch_data(url)
|
|
|
|
# 保存文件
|
|
async with aiofiles.open(file_path, 'wb') as out_file:
|
|
await out_file.write(response.content)
|
|
|
|
# 返回文件内容
|
|
return FileResponse(path=file_path, filename=file_name, media_type="video/mp4")
|
|
|
|
# 下载图片文件/Download image file
|
|
elif data_type == 'image':
|
|
# 压缩文件属性/Compress file properties
|
|
zip_file_name = f"{file_prefix}{platform}_{aweme_id}_images.zip" if not with_watermark else f"{file_prefix}{platform}_{aweme_id}_images_watermark.zip"
|
|
zip_file_path = os.path.join(download_path, zip_file_name)
|
|
|
|
# 判断文件是否存在,存在就直接返回、
|
|
if os.path.exists(zip_file_path):
|
|
return FileResponse(path=zip_file_path, filename=zip_file_name, media_type="application/zip")
|
|
|
|
# 获取图片文件/Get image file
|
|
urls = data.get('image_data').get('no_watermark_image_list') if not with_watermark else data.get(
|
|
'image_data').get('watermark_image_list')
|
|
image_file_list = []
|
|
for url in urls:
|
|
# 请求图片文件/Request image file
|
|
response = await fetch_data(url)
|
|
index = int(urls.index(url))
|
|
content_type = response.headers.get('content-type')
|
|
file_format = content_type.split('/')[1]
|
|
file_name = f"{file_prefix}{platform}_{aweme_id}_{index + 1}.{file_format}" if not with_watermark else f"{file_prefix}{platform}_{aweme_id}_{index + 1}_watermark.{file_format}"
|
|
file_path = os.path.join(download_path, file_name)
|
|
image_file_list.append(file_path)
|
|
|
|
# 保存文件/Save file
|
|
async with aiofiles.open(file_path, 'wb') as out_file:
|
|
await out_file.write(response.content)
|
|
|
|
# 压缩文件/Compress file
|
|
with zipfile.ZipFile(zip_file_path, 'w') as zip_file:
|
|
for image_file in image_file_list:
|
|
zip_file.write(image_file, os.path.basename(image_file))
|
|
|
|
# 返回压缩文件/Return compressed file
|
|
return FileResponse(path=zip_file_path, filename=zip_file_name, media_type="application/zip")
|
|
|
|
# 异常处理/Exception handling
|
|
except Exception as e:
|
|
code = 400
|
|
return ErrorResponseModel(code=code, message=str(e), router=request.url.path, params=dict(request.query_params))
|
|
|