375 lines
13 KiB
Python
375 lines
13 KiB
Python
"""
|
||
抖音发布示例
|
||
演示抖音平台的各种发布场景。
|
||
"""
|
||
import asyncio
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
# 添加项目根目录到Python路径
|
||
project_root = Path(__file__).parent.parent
|
||
sys.path.insert(0, str(project_root))
|
||
|
||
from core.publisher import Publisher
|
||
from core.models import VideoContent, PlatformType, AccountInfo
|
||
from utils.logger import setup_logger, get_logger
|
||
|
||
# 设置日志
|
||
setup_logger(level="INFO")
|
||
logger = get_logger(__name__)
|
||
|
||
|
||
async def douyin_video_publish_example():
|
||
"""抖音视频发布示例"""
|
||
print("=" * 60)
|
||
print("抖音视频发布示例")
|
||
print("=" * 60)
|
||
|
||
async with Publisher(headless=False) as publisher:
|
||
# 设置账号
|
||
account_name = "your_douyin_account" # 替换为实际账号名
|
||
print(f"1. 设置抖音账号: {account_name}")
|
||
|
||
success = await publisher.setup_platform("douyin", account_name)
|
||
if not success:
|
||
print("❌ 账号设置失败,请检查网络和账号信息")
|
||
return
|
||
|
||
print("✅ 账号设置成功")
|
||
|
||
# 创建多种类型的视频内容
|
||
videos = [
|
||
# 娱乐搞笑视频
|
||
VideoContent(
|
||
title="😂 今日最佳搞笑时刻",
|
||
description="收集了一些超级搞笑的瞬间,保证让你笑出声!记得点赞关注哦~ #搞笑 #日常 #娱乐",
|
||
video_path="media/videos/funny_moments.mp4", # 替换为实际视频路径
|
||
tags=["搞笑", "日常", "娱乐", "短视频"]
|
||
),
|
||
|
||
# 生活技巧视频
|
||
VideoContent(
|
||
title="🔥 超实用生活技巧分享",
|
||
description="分享5个超级实用的生活小技巧,让你的生活更加便利。学会了记得分享给朋友哦!#生活技巧 #实用 #分享",
|
||
video_path="media/videos/life_hacks.mp4", # 替换为实际视频路径
|
||
tags=["生活技巧", "实用", "分享", "教程"]
|
||
),
|
||
|
||
# 美食制作视频
|
||
VideoContent(
|
||
title="🍜 10分钟搞定一碗美味面条",
|
||
description="忙碌工作日也能吃到美食!今天分享一个超简单的面条做法,10分钟就能搞定,味道还不错哦!#美食 #教程 #快手菜",
|
||
video_path="media/videos/quick_noodles.mp4", # 替换为实际视频路径
|
||
tags=["美食", "教程", "快手菜", "面条"]
|
||
),
|
||
|
||
# 健身运动视频
|
||
VideoContent(
|
||
title="💪 居家健身5分钟燃脂训练",
|
||
description="不需要任何器械,在家就能做的燃脂训练!每天坚持5分钟,让你拥有好身材。#健身 #燃脂 #运动",
|
||
video_path="media/videos/home_workout.mp4", # 替换为实际视频路径
|
||
tags=["健身", "燃脂", "运动", "居家"]
|
||
)
|
||
]
|
||
|
||
# 发布视频
|
||
for i, video in enumerate(videos, 1):
|
||
print(f"\n{i}. 发布视频: {video.title}")
|
||
try:
|
||
result = await publisher.publish("douyin", video, account_name)
|
||
|
||
if result.success:
|
||
print(f"✅ 发布成功!")
|
||
print(f" 任务ID: {result.task_id}")
|
||
print(f" 耗时: {result.duration:.2f}秒")
|
||
if result.published_url:
|
||
print(f" 链接: {result.published_url}")
|
||
else:
|
||
print(f"❌ 发布失败: {result.message}")
|
||
if result.error_details:
|
||
print(f" 错误详情: {result.error_details}")
|
||
|
||
except Exception as e:
|
||
print(f"❌ 发布异常: {e}")
|
||
|
||
# 发布间隔(避免频繁操作)
|
||
if i < len(videos):
|
||
wait_time = 15 + (i * 5) # 递增等待时间
|
||
print(f"⏳ 等待{wait_time}秒后发布下一个视频...")
|
||
await asyncio.sleep(wait_time)
|
||
|
||
|
||
async def douyin_batch_upload_example():
|
||
"""抖音批量上传示例"""
|
||
print("=" * 60)
|
||
print("抖音批量上传示例")
|
||
print("=" * 60)
|
||
|
||
# 批量准备视频内容
|
||
video_contents = [
|
||
VideoContent(
|
||
title=f"批量测试视频 {i+1}",
|
||
description=f"这是第{i+1}个批量上传的测试视频,内容为{i+1}。",
|
||
video_path=f"media/videos/batch_test_{i+1}.mp4", # 替换为实际视频路径
|
||
tags=[f"批量测试{i+1}", "自动化", "测试"]
|
||
)
|
||
for i in range(3)
|
||
]
|
||
|
||
async with Publisher(headless=False) as publisher:
|
||
# 设置账号
|
||
account_name = "your_douyin_account" # 替换为实际账号名
|
||
success = await publisher.setup_platform("douyin", account_name)
|
||
|
||
if not success:
|
||
print("❌ 账号设置失败")
|
||
return
|
||
|
||
print("✅ 账号设置成功")
|
||
print(f"开始批量上传 {len(video_contents)} 个视频...")
|
||
|
||
# 创建发布任务
|
||
from core.models import PublishTask
|
||
tasks = []
|
||
for i, content in enumerate(video_contents):
|
||
task = PublishTask(
|
||
id=f"douyin_batch_{i+1}",
|
||
platform=PlatformType.DOUYIN,
|
||
account=AccountInfo(
|
||
platform=PlatformType.DOUYIN,
|
||
username=account_name,
|
||
cookie_file=f"{account_name}.json"
|
||
),
|
||
content=content,
|
||
max_retries=2 # 设置重试次数
|
||
)
|
||
tasks.append(task)
|
||
|
||
# 执行批量上传
|
||
try:
|
||
results = await publisher.batch_publish(tasks)
|
||
|
||
# 统计结果
|
||
success_count = sum(1 for r in results if r.success)
|
||
print(f"\n📊 批量上传完成:")
|
||
print(f" 成功: {success_count}/{len(results)}")
|
||
print(f" 失败: {len(results) - success_count}/{len(results)}")
|
||
|
||
# 详细结果
|
||
for result in results:
|
||
status = "✅" if result.success else "❌"
|
||
duration = f" ({result.duration:.1f}s)" if result.duration else ""
|
||
print(f" {status} {result.task_id}: {result.message}{duration}")
|
||
|
||
except Exception as e:
|
||
print(f"❌ 批量上传异常: {e}")
|
||
|
||
|
||
async def douyin_upload_with_progress_example():
|
||
"""抖音上传进度监控示例"""
|
||
print("=" * 60)
|
||
print("抖音上传进度监控示例")
|
||
print("=" * 60)
|
||
|
||
async with Publisher(headless=False) as publisher:
|
||
# 设置账号
|
||
account_name = "your_douyin_account" # 替换为实际账号名
|
||
success = await publisher.setup_platform("douyin", account_name)
|
||
|
||
if not success:
|
||
print("❌ 账号设置失败")
|
||
return
|
||
|
||
print("✅ 账号设置成功")
|
||
|
||
# 创建一个较大的视频文件用于测试进度监控
|
||
video = VideoContent(
|
||
title="上传进度测试视频 📊",
|
||
description="这是一个用于测试上传进度监控功能的视频,文件比较大,可以清楚地看到上传进度。",
|
||
video_path="media/videos/large_video.mp4", # 替换为实际的大视频路径
|
||
tags=["测试", "上传", "进度监控"]
|
||
)
|
||
|
||
print(f"\n开始上传视频: {video.title}")
|
||
print("注意:这会打开浏览器窗口,你可以看到实际的上传过程")
|
||
|
||
try:
|
||
result = await publisher.publish("douyin", video, account_name)
|
||
|
||
if result.success:
|
||
print(f"✅ 视频上传成功!")
|
||
print(f" 任务ID: {result.task_id}")
|
||
print(f" 总耗时: {result.duration:.2f}秒")
|
||
else:
|
||
print(f"❌ 视频上传失败: {result.message}")
|
||
|
||
except Exception as e:
|
||
print(f"❌ 上传异常: {e}")
|
||
|
||
|
||
async def douyin_content_validation_example():
|
||
"""抖音内容验证示例"""
|
||
print("=" * 60)
|
||
print("抖音内容验证示例")
|
||
print("=" * 60)
|
||
|
||
async with Publisher() as publisher:
|
||
# 测试各种内容验证场景
|
||
test_cases = [
|
||
# 有效内容
|
||
{
|
||
"name": "有效的视频内容",
|
||
"content": VideoContent(
|
||
title="有效标题",
|
||
description="有效描述",
|
||
video_path="test.mp4"
|
||
),
|
||
"expected": True
|
||
},
|
||
|
||
# 无效内容 - 空标题
|
||
{
|
||
"name": "空标题",
|
||
"content": VideoContent(
|
||
title="",
|
||
description="有效描述",
|
||
video_path="test.mp4"
|
||
),
|
||
"expected": False
|
||
},
|
||
|
||
# 无效内容 - 空描述
|
||
{
|
||
"name": "空描述",
|
||
"content": VideoContent(
|
||
title="有效标题",
|
||
description="",
|
||
video_path="test.mp4"
|
||
),
|
||
"expected": False
|
||
},
|
||
|
||
# 无效内容 - 不支持的格式
|
||
{
|
||
"name": "不支持的文件格式",
|
||
"content": VideoContent(
|
||
title="有效标题",
|
||
description="有效描述",
|
||
video_path="test.avi" # 假设不支持avi格式
|
||
),
|
||
"expected": False
|
||
},
|
||
|
||
# 无效内容 - 视频时长过长
|
||
{
|
||
"name": "视频时长过长",
|
||
"content": VideoContent(
|
||
title="有效标题",
|
||
description="有效描述",
|
||
video_path="test.mp4",
|
||
duration=1200 # 20分钟,假设平台限制为10分钟
|
||
),
|
||
"expected": False
|
||
}
|
||
]
|
||
|
||
print("开始内容验证测试...")
|
||
for i, test_case in enumerate(test_cases, 1):
|
||
print(f"\n{i}. 测试: {test_case['name']}")
|
||
|
||
try:
|
||
is_valid, error_msg = await publisher.validate_content(
|
||
"douyin",
|
||
test_case['content']
|
||
)
|
||
|
||
if is_valid == test_case['expected']:
|
||
print(f" ✅ 验证结果符合预期")
|
||
else:
|
||
print(f" ❌ 验证结果不符合预期")
|
||
print(f" 期望: {test_case['expected']}")
|
||
print(f" 实际: {is_valid}")
|
||
|
||
if not is_valid:
|
||
print(f" 错误信息: {error_msg}")
|
||
|
||
except Exception as e:
|
||
print(f" ❌ 验证异常: {e}")
|
||
|
||
|
||
async def douyin_quick_publish_example():
|
||
"""抖音快速发布示例"""
|
||
print("=" * 60)
|
||
print("抖音快速发布示例")
|
||
print("=" * 60)
|
||
|
||
try:
|
||
from core.publisher import publish_to_douyin
|
||
|
||
# 快速发布单个视频
|
||
print("1. 使用快速发布功能...")
|
||
result = await publish_to_douyin(
|
||
title="🎬 快速发布测试视频",
|
||
description="这是使用快速发布功能上传的测试视频,简单方便!#快速发布 #测试 #自动化",
|
||
video_path="media/videos/quick_test.mp4", # 替换为实际视频路径
|
||
tags=["快速发布", "测试", "自动化"],
|
||
account_name="your_douyin_account", # 替换为实际账号名
|
||
headless=False
|
||
)
|
||
|
||
if result.success:
|
||
print(f"✅ 快速发布成功!")
|
||
print(f" 任务ID: {result.task_id}")
|
||
print(f" 耗时: {result.duration:.2f}秒")
|
||
else:
|
||
print(f"❌ 快速发布失败: {result.message}")
|
||
|
||
except Exception as e:
|
||
print(f"❌ 快速发布异常: {e}")
|
||
|
||
|
||
async def main():
|
||
"""主函数"""
|
||
print("🚀 抖音发布示例")
|
||
print("=" * 60)
|
||
print("请确保:")
|
||
print("1. 替换示例中的账号名称")
|
||
print("2. 准备好视频文件")
|
||
print("3. 确保网络连接正常")
|
||
print("4. 视频文件格式符合要求(mp4、mov等)")
|
||
print("=" * 60)
|
||
|
||
try:
|
||
# 运行示例
|
||
print("选择要运行的示例:")
|
||
print("1. 视频发布")
|
||
print("2. 批量上传")
|
||
print("3. 上传进度监控")
|
||
print("4. 内容验证")
|
||
print("5. 快速发布")
|
||
|
||
choice = input("\n请输入选择 (1-5): ").strip()
|
||
|
||
if choice == "1":
|
||
await douyin_video_publish_example()
|
||
elif choice == "2":
|
||
await douyin_batch_upload_example()
|
||
elif choice == "3":
|
||
await douyin_upload_with_progress_example()
|
||
elif choice == "4":
|
||
await douyin_content_validation_example()
|
||
elif choice == "5":
|
||
await douyin_quick_publish_example()
|
||
else:
|
||
print("❌ 无效选择")
|
||
|
||
except KeyboardInterrupt:
|
||
print("\n⏹️ 用户中断")
|
||
except Exception as e:
|
||
print(f"\n❌ 运行异常: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
asyncio.run(main()) |