mirror of
https://github.com/dreammis/social-auto-upload.git
synced 2026-09-17 17:38:37 +08:00
feat(douyin): 添加 --bgm 参数支持选择音乐
This commit is contained in:
+4
-2
@@ -105,9 +105,11 @@ sau douyin check --account <account_name>
|
||||
sau douyin upload-video --account <account_name> --file videos/demo.mp4 --title "示例标题" --desc "示例简介"
|
||||
图文正文1:
|
||||
$noteText = @"图文正文"@
|
||||
sau douyin upload-note --account <account_name> --images videos/demo1.png videos/demo2.png --title "图文标题" --note $noteText --tags 'tag1,tag2'
|
||||
sau douyin upload-note --account <account_name> --images videos/demo1.png videos/demo2.png --title "图文标题" --note $noteText --tags 'tag1,tag2'
|
||||
图文正文2:
|
||||
sau douyin upload-note --account <account_name> --images videos/demo1.png videos/demo2.png --title "图文标题" --notef '图文文件路径' --tags 'tag1,tag2'
|
||||
sau douyin upload-note --account <account_name> --images videos/demo1.png videos/demo2.png --title "图文标题" --notef '图文文件路径' --tags 'tag1,tag2'
|
||||
添加 BGM(可选):
|
||||
sau douyin upload-note --account <account_name> --images videos/demo1.png videos/demo2.png --title "图文标题" --note $noteText --tags 'tag1,tag2' --bgm '音乐名称'
|
||||
```
|
||||
|
||||
抖音卡login手动获取cookie:
|
||||
|
||||
@@ -74,6 +74,7 @@ class DouyinNoteUploadRequest:
|
||||
publish_strategy: str = DOUYIN_PUBLISH_STRATEGY_IMMEDIATE
|
||||
debug: bool = True
|
||||
headless: bool = True
|
||||
bgm: str = ""
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
@@ -323,6 +324,7 @@ async def upload_note(request: DouyinNoteUploadRequest) -> Path:
|
||||
publish_strategy=request.publish_strategy,
|
||||
debug=request.debug,
|
||||
headless=request.headless,
|
||||
bgm=request.bgm,
|
||||
)
|
||||
await app.douyin_upload_note()
|
||||
return account_file
|
||||
@@ -549,6 +551,7 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
upload_note_parser.add_argument("--note", default="", help="Optional note content")
|
||||
upload_note_parser.add_argument("--notef", default="", help="Read note content from file (txt/md)")
|
||||
upload_note_parser.add_argument("--tags", default="", help="Comma-separated tags, such as tag1,tag2")
|
||||
upload_note_parser.add_argument("--bgm", default="", help="BGM music name to search and select")
|
||||
upload_note_parser.add_argument("--schedule", type=schedule_value, help=f"Schedule time in {schedule_help}")
|
||||
add_runtime_flags(upload_note_parser)
|
||||
|
||||
@@ -707,6 +710,7 @@ async def dispatch(args: argparse.Namespace) -> int:
|
||||
publish_strategy=publish_strategy,
|
||||
debug=args.debug,
|
||||
headless=args.headless,
|
||||
bgm=args.bgm or "",
|
||||
)
|
||||
await upload_note(request)
|
||||
print(f"Douyin note upload submitted: {len(request.image_files)} images")
|
||||
|
||||
@@ -400,6 +400,72 @@ class DouYinBaseUploader(BaseVideoUploader):
|
||||
except Exception as exc:
|
||||
douyin_logger.warning(_msg("🧾", f"自主声明设置失败,跳过该步骤继续发布:{exc}"))
|
||||
|
||||
async def select_bgm(self, page: Page, bgm_name: str) -> bool:
|
||||
"""为图文发布选择 BGM:可选增强功能,搜索无结果或异常均跳过不中断发布。"""
|
||||
try:
|
||||
# 点击「选择音乐」按钮
|
||||
music_entry = page.locator('text="选择音乐"').nth(1)
|
||||
if not await music_entry.count():
|
||||
music_entry = page.locator('text="选择音乐"').first
|
||||
await music_entry.wait_for(state="visible", timeout=10000)
|
||||
await music_entry.click()
|
||||
|
||||
# 等待侧边栏出现并搜索
|
||||
sidesheet = page.locator(".semi-sidesheet-content").first
|
||||
await sidesheet.wait_for(state="visible", timeout=8000)
|
||||
search_input = sidesheet.locator('input.semi-input[placeholder="搜索音乐"]').first
|
||||
await search_input.wait_for(state="visible", timeout=5000)
|
||||
await search_input.fill(bgm_name)
|
||||
await search_input.press("Enter")
|
||||
|
||||
# 等待搜索结果
|
||||
await asyncio.sleep(2)
|
||||
first_card = sidesheet.locator(".card-container-tmocjc").first
|
||||
try:
|
||||
await first_card.wait_for(state="visible", timeout=8000)
|
||||
except Exception:
|
||||
douyin_logger.warning(_msg("🎵", f"音乐「{bgm_name}」搜索结果为空,小人跳过"))
|
||||
await self._close_music_sidesheet(page)
|
||||
return False
|
||||
|
||||
# 打印找到的音乐名称
|
||||
try:
|
||||
song_name_el = first_card.locator(".song-name-oRge4d").first
|
||||
if await song_name_el.count():
|
||||
song_name = await song_name_el.inner_text()
|
||||
douyin_logger.info(_msg("🎵", f"小人找到了: {song_name}"))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# JS 点击「使用」(按钮 visibility:hidden,普通 click 无效)
|
||||
apply_btn = first_card.locator(".apply-btn-LUPP0D").first
|
||||
await apply_btn.evaluate("el => el.click()")
|
||||
douyin_logger.info(_msg("🥳", f"BGM「{bgm_name}」已应用"))
|
||||
|
||||
# 等待侧边栏关闭,超时则手动关闭
|
||||
try:
|
||||
await sidesheet.wait_for(state="hidden", timeout=5000)
|
||||
except Exception:
|
||||
await self._close_music_sidesheet(page)
|
||||
|
||||
return True
|
||||
except Exception as exc:
|
||||
douyin_logger.warning(_msg("🎵", f"添加 BGM 时出错,跳过该步骤继续发布:{exc}"))
|
||||
try:
|
||||
await self._close_music_sidesheet(page)
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
|
||||
async def _close_music_sidesheet(self, page: Page) -> None:
|
||||
try:
|
||||
close_btn = page.locator(".semi-sidesheet-close").first
|
||||
if await close_btn.count() and await close_btn.is_visible():
|
||||
await close_btn.click()
|
||||
await asyncio.sleep(1)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
class DouYinVideo(DouYinBaseUploader):
|
||||
def __init__(
|
||||
@@ -619,6 +685,7 @@ class DouYinNote(DouYinBaseUploader):
|
||||
publish_strategy: str = DOUYIN_PUBLISH_STRATEGY_IMMEDIATE,
|
||||
debug: bool = DEBUG_MODE,
|
||||
headless: bool = LOCAL_CHROME_HEADLESS,
|
||||
bgm: str = "",
|
||||
):
|
||||
super().__init__(
|
||||
publish_date=publish_date,
|
||||
@@ -631,6 +698,7 @@ class DouYinNote(DouYinBaseUploader):
|
||||
self.note = note or ""
|
||||
self.title = title or (self.note[:30] if self.note else "")
|
||||
self.tags = tags or []
|
||||
self.bgm = bgm or ""
|
||||
|
||||
async def validate_upload_args(self):
|
||||
await self.validate_base_args()
|
||||
@@ -682,8 +750,15 @@ class DouYinNote(DouYinBaseUploader):
|
||||
await asyncio.sleep(1)
|
||||
douyin_logger.info(_msg("✍️", "小人开始填标题、描述和话题"))
|
||||
await self.fill_title_and_description(page, self.title, self.note, self.tags)
|
||||
title_len = len(self.title) if self.title else 0
|
||||
tags_text = " ".join(f"#{t}" for t in self.tags) if self.tags else ""
|
||||
desc_and_tags_len = len(self.note or "") + (len(tags_text) + 2 if self.tags else 0)
|
||||
douyin_logger.info(_msg("📝", f"标题总字数: {title_len},描述+话题总字数: {desc_and_tags_len}"))
|
||||
douyin_logger.info(_msg("🏷️", f"小人一共贴了 {len(self.tags)} 个话题"))
|
||||
|
||||
if self.bgm:
|
||||
await self.select_bgm(page, self.bgm)
|
||||
|
||||
if self.publish_strategy == DOUYIN_PUBLISH_STRATEGY_SCHEDULED and self.publish_date != 0:
|
||||
await self.set_schedule_time_douyin(page, self.publish_date)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user