# -*- coding: utf-8 -*-
import os
import re
import sys
import time
import json
import argparse
import requests
import logging
from tqdm import tqdm
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor

# 设置日志
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")

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"
}

# 获取视频信息
def get_video_info(video_url):
    logging.info(f"解析视频链接: {video_url}")
    
    # 获取网页 HTML
    response = requests.get(video_url, headers=HEADERS, timeout=10)
    if response.status_code != 200:
        logging.error("无法获取视频页面")
        return None
    
    # 解析 HTML
    soup = BeautifulSoup(response.text, "html.parser")
    video_tag = soup.find("script", text=re.compile("window.__INIT_PROPS__"))
    if not video_tag:
        logging.error("无法解析视频信息")
        return None

    # 提取 JSON 数据
    match = re.search(r'window\.__INIT_PROPS__\s?=\s?({.*?});', video_tag.string)
    if not match:
        logging.error("未找到视频数据")
        return None
    
    try:
        video_json = json.loads(match.group(1))
        video_data = video_json.get("/video/", {}).get("video", {})
        video_url = video_data.get("playAddr")
        title = video_data.get("title", "douyin_video")
        
        if not video_url:
            logging.error("未找到视频播放地址")
            return None
        
        return {"url": video_url, "title": title}
    
    except json.JSONDecodeError:
        logging.error("解析 JSON 失败")
        return None

# 下载视频
def download_video(video_url, save_path):
    logging.info(f"开始下载: {video_url}")

    # 发送请求
    response = requests.get(video_url, stream=True, headers=HEADERS)
    total_size = int(response.headers.get("content-length", 0))
    
    with open(save_path, "wb") as file, tqdm(
        desc="下载进度",
        total=total_size,
        unit="B",
        unit_scale=True,
        unit_divisor=1024
    ) as bar:
        for chunk in response.iter_content(chunk_size=1024):
            if chunk:
                file.write(chunk)
                bar.update(len(chunk))

    logging.info(f"下载完成: {save_path}")

# 多线程下载多个视频
def batch_download(urls, output_dir):
    os.makedirs(output_dir, exist_ok=True)
    with ThreadPoolExecutor(max_workers=3) as executor:
        futures = []
        for url in urls:
            video_info = get_video_info(url)
            if video_info:
                filename = f"{video_info['title']}.mp4"
                save_path = os.path.join(output_dir, filename)
                futures.append(executor.submit(download_video, video_info["url"], save_path))

        for future in futures:
            future.result()  # 确保所有任务完成

# 解析命令行参数
def main():
    parser = argparse.ArgumentParser(description="抖音无水印视频下载工具")
    parser.add_argument("url", nargs="+", help="抖音视频链接（支持多个）")
    parser.add_argument("-o", "--output", default="./videos", help="下载保存目录")
    args = parser.parse_args()

    batch_download(args.url, args.output)

if __name__ == "__main__":
    main()
