social_media_auto_publisher/advanced_demo.py

339 lines
12 KiB
Python
Raw Normal View History

2025-11-12 00:28:07 +08:00
#!/usr/bin/env python3
"""
高级演示测试 - 展示项目核心功能
"""
import asyncio
import sys
from pathlib import Path
from datetime import datetime
from dataclasses import dataclass, field
from enum import Enum
from typing import List, Optional, Dict, Any
# 使用我们之前测试过的可用模型定义
class PlatformType(Enum):
XIAOHONGSHU = "xiaohongshu"
DOUYIN = "douyin"
@dataclass
class ImageNote:
title: str
description: str
images: List[str] = field(default_factory=list)
tags: List[str] = field(default_factory=list)
visibility: str = "public"
cover_image: Optional[str] = None
@dataclass
class VideoContent:
title: str
description: str
video_path: str
tags: List[str] = field(default_factory=list)
visibility: str = "public"
cover_image: Optional[str] = None
@dataclass
class AccountInfo:
platform: PlatformType
username: str
cookie_file: str
is_active: bool = True
class SimplePublisher:
"""简化的发布器演示类"""
def __init__(self):
self.browser = None
self.page = None
async def setup_browser(self, headless=False):
"""设置浏览器"""
try:
from playwright.async_api import async_playwright
self.playwright = await async_playwright().start()
self.browser = await self.playwright.chromium.launch(
headless=headless,
args=[
'--no-sandbox',
'--disable-blink-features=AutomationControlled'
]
)
# 设置用户代理
context = await self.browser.new_context(
user_agent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36'
)
self.page = await context.new_page()
# 注入反检测脚本
await self.page.add_init_script("""
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined,
});
""")
return True
except Exception as e:
print(f"❌ 浏览器设置失败: {e}")
return False
async def test_platform_access(self, platform, account_info):
"""测试平台访问(不登录)"""
print(f"\n🌐 测试{platform.value}平台访问")
print("-" * 40)
try:
if platform == PlatformType.XIAOHONGSHU:
# 访问小红书创作者中心
await self.page.goto("https://creator.xiaohongshu.com/", timeout=10000)
await asyncio.sleep(2)
# 检查页面是否正常加载
title = await self.page.title()
print(f"✅ 页面加载成功: {title}")
# 检查是否有登录相关元素
login_elements = await self.page.query_selector_all('[class*="login"], [class*="auth"], button:has-text("登录")')
if login_elements:
print(f"✅ 检测到 {len(login_elements)} 个登录相关元素")
return True
elif platform == PlatformType.DOUYIN:
# 访问抖音创作者中心
await self.page.goto("https://creator.douyin.com/", timeout=10000)
await asyncio.sleep(2)
# 检查页面是否正常加载
title = await self.page.title()
print(f"✅ 页面加载成功: {title}")
# 检查是否有登录相关元素
login_elements = await self.page.query_selector_all('[class*="login"], [class*="auth"], button:has-text("登录")')
if login_elements:
print(f"✅ 检测到 {len(login_elements)} 个登录相关元素")
return True
except Exception as e:
print(f"❌ 平台访问失败: {e}")
return False
async def simulate_content_creation(self, content, platform):
"""模拟内容创建过程(不实际提交)"""
print(f"\n📝 模拟{platform.value}内容创建")
print("-" * 40)
try:
if platform == PlatformType.XIAOHONGSHU:
# 模拟访问图文笔记发布页面
await self.page.goto("https://creator.xiaohongshu.com/publish/publish", timeout=10000)
await asyncio.sleep(3)
# 检查是否到达发布页面
url = self.page.url
if "publish" in url:
print("✅ 成功访问图文笔记发布页面")
# 模拟查找标题输入框
title_input = await self.page.query_selector('input[placeholder*="标题"], textarea[placeholder*="标题"]')
if title_input:
print("✅ 找到标题输入框")
# 只模拟输入,不实际输入
print(f"📝 准备输入标题: {content.title}")
# 模拟查找内容输入框
content_input = await self.page.query_selector('textarea[placeholder*="内容"], textarea[placeholder*="描述"]')
if content_input:
print("✅ 找到内容输入框")
print(f"📝 准备输入描述: {content.description[:30]}...")
# 模拟查找图片上传区域
upload_area = await self.page.query_selector('[class*="upload"], [data-testid*="upload"], input[type="file"]')
if upload_area:
print("✅ 找到图片上传区域")
print(f"📷 准备上传 {len(content.images)} 张图片")
return True
else:
print("❌ 未能访问发布页面,可能需要登录")
return False
elif platform == PlatformType.DOUYIN:
# 模拟访问视频上传页面
await self.page.goto("https://creator.douyin.com/creator-micro/content/upload", timeout=10000)
await asyncio.sleep(3)
# 检查页面
url = self.page.url
if "upload" in url or "content" in url:
print("✅ 成功访问内容上传页面")
# 模拟查找标题输入框
title_input = await self.page.query_selector('input[placeholder*="标题"]')
if title_input:
print("✅ 找到标题输入框")
print(f"📝 准备输入标题: {content.title}")
# 模拟查找描述输入框
desc_input = await self.page.query_selector('textarea[placeholder*="描述"]')
if desc_input:
print("✅ 找到描述输入框")
print(f"📝 准备输入描述: {content.description[:30]}...")
# 模拟查找视频上传区域
video_upload = await self.page.query_selector('[class*="upload"], input[type="file"][accept*="video"]')
if video_upload:
print("✅ 找到视频上传区域")
print(f"🎬 准备上传视频: {content.video_path}")
return True
else:
print("❌ 未能访问上传页面,可能需要登录")
return False
except Exception as e:
print(f"❌ 内容创建模拟失败: {e}")
return False
async def cleanup(self):
"""清理资源"""
if self.page:
await self.page.close()
if self.browser:
await self.browser.close()
if hasattr(self, 'playwright'):
await self.playwright.stop()
def create_sample_content():
"""创建示例内容"""
contents = []
# 小红书图文笔记
xhs_note = ImageNote(
title="今日美食分享 🍜| 超好吃的家常面",
description="今天做了特别好吃的家常面,汤底浓郁,面条劲道,配上特制的酱料,简直是绝配!详细做法在图片里,大家一定要试试看~\n\n#家常美食 #面条 #美食分享 #简单易学",
images=["delicious_noodles1.jpg", "delicious_noodles2.jpg", "delicious_noodles3.jpg"],
tags=["家常美食", "面条", "美食分享", "简单易学", "今日菜单"]
)
contents.append((xhs_note, PlatformType.XIAOHONGSHU))
# 抖音视频
douyin_video = VideoContent(
title="10分钟搞定快手早餐 🥪",
description="分享一个超级简单的快手早餐做法10分钟就能搞定营养又美味上班族和学生党都适合~\n\n#快手早餐 #早餐教程 #简单易学 #美食vlog",
video_path="quick_breakfast.mp4",
tags=["快手早餐", "早餐教程", "简单易学", "美食vlog", "生活技巧"]
)
contents.append((douyin_video, PlatformType.DOUYIN))
return contents
async def main():
"""主演示函数"""
print("🚀 社交媒体自动发布器 - 高级功能演示")
print("📋 这个演示会访问真实平台页面,但不会发布任何内容")
print("=" * 70)
# 创建示例内容和账号
contents = create_sample_content()
# 创建测试账号
test_accounts = {
PlatformType.XIAOHONGSHU: AccountInfo(
platform=PlatformType.XIAOHONGSHU,
username="demo_xhs_user",
cookie_file="demo_xhs_user.json"
),
PlatformType.DOUYIN: AccountInfo(
platform=PlatformType.DOUYIN,
username="demo_douyin_user",
cookie_file="demo_douyin_user.json"
)
}
# 创建发布器
publisher = SimplePublisher()
try:
# 设置浏览器(显示模式,便于观察)
print("\n🌐 1. 设置浏览器环境")
if await publisher.setup_browser(headless=False):
print("✅ 浏览器设置成功")
else:
print("❌ 浏览器设置失败")
return False
# 测试每个平台
for content, platform in contents:
print(f"\n{'='*70}")
print(f"📱 测试平台: {platform.value}")
print(f"📝 内容: {content.title}")
print(f"{'='*70}")
# 1. 测试平台访问
if await publisher.test_platform_access(platform, test_accounts[platform]):
# 2. 模拟内容创建
await publisher.simulate_content_creation(content, platform)
# 3. 显示内容预览
print(f"\n📋 内容预览:")
print(f" 标题: {content.title}")
print(f" 描述: {content.description[:100]}...")
print(f" 标签: {', '.join(content.tags)}")
if isinstance(content, ImageNote):
print(f" 图片: {len(content.images)}")
elif isinstance(content, VideoContent):
print(f" 视频: {content.video_path}")
print(f"\n⏳ 等待3秒后测试下一个平台...")
await asyncio.sleep(3)
else:
print(f"{platform.value}平台访问失败")
print(f"\n{'='*70}")
print("🎉 演示测试完成!")
print("\n📝 演示总结:")
print("✅ 浏览器环境设置成功")
print("✅ 平台页面访问测试")
print("✅ 内容创建流程模拟")
print("✅ 发布界面元素检测")
print(f"\n📋 实际使用时:")
print("1. 准备真实的图片和视频文件")
print("2. 运行完整的登录流程(扫码登录)")
print("3. 使用真实的账号信息")
print("4. 执行实际的内容发布")
return True
except Exception as e:
print(f"\n❌ 演示过程中出现异常: {e}")
import traceback
traceback.print_exc()
return False
finally:
# 清理资源
await publisher.cleanup()
if __name__ == "__main__":
print("⚠️ 注意: 这个演示会打开浏览器窗口,访问真实网站页面")
print("⚠️ 但不会进行任何登录操作或内容发布")
print("⚠️ 请在30秒内观察浏览器行为或按Ctrl+C退出")
print("\n按回车键继续演示或按Ctrl+C退出...")
try:
input()
result = asyncio.run(main())
sys.exit(0 if result else 1)
except KeyboardInterrupt:
print("\n⏹️ 用户中断演示")
sys.exit(0)