fix(douyin): version_2 发布页适配——标题超时/封面输入/话题上限
- 标题/描述等待 10s→120s:version_2(post/video) 要等视频上传完才渲染表单(实测约40s) - 封面上传修正:封面弹窗有4个隐藏input,前2个是左侧AI参考图,真封面是 nth(1);旧 .first 传错位置导致封面不生效 - set_thumbnail 先清 shepherd 引导浮层,避免拦截选择封面点击 - 完成按钮用 exact 文本,避免误中完成编辑
This commit is contained in:
@@ -264,12 +264,13 @@ class DouYinBaseUploader(BaseVideoUploader):
|
|||||||
|
|
||||||
async def fill_title_and_description(self, page: Page, title: str, description: str, tags: list[str] | None = None):
|
async def fill_title_and_description(self, page: Page, title: str, description: str, tags: list[str] | None = None):
|
||||||
# 2026-06 抖音发布页 DOM:标题=input[placeholder*=填写作品标题],描述=div.zone-container[contenteditable]
|
# 2026-06 抖音发布页 DOM:标题=input[placeholder*=填写作品标题],描述=div.zone-container[contenteditable]
|
||||||
|
# version_2(post/video) 发布页要等视频上传完才渲染表单(实测约 40s),故等待超时给到 120s
|
||||||
title_input = page.locator('input[placeholder*="填写作品标题"]').first
|
title_input = page.locator('input[placeholder*="填写作品标题"]').first
|
||||||
await title_input.wait_for(state="visible", timeout=10000)
|
await title_input.wait_for(state="visible", timeout=120000)
|
||||||
await title_input.fill(title[:30])
|
await title_input.fill(title[:30])
|
||||||
|
|
||||||
description_editor = page.locator('div.zone-container[contenteditable="true"]').first
|
description_editor = page.locator('div.zone-container[contenteditable="true"]').first
|
||||||
await description_editor.wait_for(state="visible", timeout=10000)
|
await description_editor.wait_for(state="visible", timeout=120000)
|
||||||
await description_editor.click()
|
await description_editor.click()
|
||||||
await page.keyboard.press("Control+KeyA")
|
await page.keyboard.press("Control+KeyA")
|
||||||
await page.keyboard.press("Delete")
|
await page.keyboard.press("Delete")
|
||||||
@@ -467,29 +468,46 @@ class DouYinVideo(DouYinBaseUploader):
|
|||||||
return
|
return
|
||||||
|
|
||||||
douyin_logger.info(_msg("🏃", "小人正在设置视频封面"))
|
douyin_logger.info(_msg("🏃", "小人正在设置视频封面"))
|
||||||
await page.click('text="选择封面"', force=True)
|
# 先清掉 shepherd 新手引导浮层,否则它会拦截“选择封面”点击导致弹窗打不开
|
||||||
|
await page.evaluate(
|
||||||
|
"() => document.querySelectorAll('.shepherd-element,.shepherd-modal-overlay-container').forEach(e=>e.remove())"
|
||||||
|
)
|
||||||
|
await page.get_by_text("选择封面", exact=True).first.click(force=True)
|
||||||
cover_locator_str = 'div.dy-creator-content-modal'
|
cover_locator_str = 'div.dy-creator-content-modal'
|
||||||
cover_locator = page.locator(cover_locator_str).first
|
cover_locator = page.locator(cover_locator_str).first
|
||||||
await page.wait_for_selector(cover_locator_str, timeout=15000)
|
await page.wait_for_selector(cover_locator_str, timeout=20000)
|
||||||
|
|
||||||
upload_input = cover_locator.locator("input.semi-upload-hidden-input").first
|
await page.wait_for_timeout(1500)
|
||||||
|
# version_2 封面弹窗有 4 个隐藏 file input:
|
||||||
if self.thumbnail_landscape_path:
|
# [0]/[1] 左侧“AI生成参考图”上传/替换,[2]/[3] 才是“上传封面”/替换。
|
||||||
await page.wait_for_timeout(1000)
|
# 旧代码用 .first 传到了 AI 参考图(不会成为封面)→ 这就是“传了却没封面”的根因。
|
||||||
await upload_input.set_input_files(self.thumbnail_landscape_path)
|
# 取 input.semi-upload-hidden-input 的第 2 个(nth(1)),即真正的封面上传输入。
|
||||||
await page.wait_for_timeout(2000)
|
cover_upload = cover_locator.locator("input.semi-upload-hidden-input").nth(1)
|
||||||
douyin_logger.info(_msg("🖼️", "横版封面上传完成"))
|
|
||||||
|
|
||||||
if self.thumbnail_portrait_path:
|
if self.thumbnail_portrait_path:
|
||||||
await cover_locator.locator('button:has-text("设置竖封面")').first.click()
|
# 弹窗默认就在“设置竖封面”页;防御性点一下 tab(已激活则忽略)
|
||||||
await page.wait_for_timeout(1000)
|
try:
|
||||||
await upload_input.set_input_files(self.thumbnail_portrait_path)
|
await cover_locator.get_by_text("设置竖封面", exact=True).first.click(timeout=3000)
|
||||||
await page.wait_for_timeout(2000)
|
await page.wait_for_timeout(800)
|
||||||
douyin_logger.info(_msg("🖼️", "竖版封面上传完成"))
|
except Exception:
|
||||||
|
pass
|
||||||
|
await cover_upload.set_input_files(self.thumbnail_portrait_path)
|
||||||
|
await page.wait_for_timeout(3000)
|
||||||
|
douyin_logger.info(_msg("🖼️", "竖版封面已上传到预览"))
|
||||||
|
elif self.thumbnail_landscape_path:
|
||||||
|
try:
|
||||||
|
await cover_locator.get_by_text("设置横封面", exact=True).first.click(timeout=3000)
|
||||||
|
await page.wait_for_timeout(800)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
await cover_upload.set_input_files(self.thumbnail_landscape_path)
|
||||||
|
await page.wait_for_timeout(3000)
|
||||||
|
douyin_logger.info(_msg("🖼️", "横版封面已上传到预览"))
|
||||||
|
|
||||||
await cover_locator.locator('button:has-text("完成")').first.click()
|
# 点红色主按钮“完成”应用封面(exact 避免误中“完成编辑”)
|
||||||
|
await cover_locator.get_by_role("button", name="完成", exact=True).first.click()
|
||||||
douyin_logger.info(_msg("🥳", "视频封面设置完成"))
|
douyin_logger.info(_msg("🥳", "视频封面设置完成"))
|
||||||
await cover_locator.wait_for(state="detached", timeout=15000)
|
await cover_locator.wait_for(state="detached", timeout=20000)
|
||||||
|
|
||||||
async def upload(self, playwright: Playwright) -> None:
|
async def upload(self, playwright: Playwright) -> None:
|
||||||
douyin_logger.info(_msg("🧍", "小人先检查 cookie、视频文件、封面和发布时间"))
|
douyin_logger.info(_msg("🧍", "小人先检查 cookie、视频文件、封面和发布时间"))
|
||||||
@@ -508,6 +526,8 @@ class DouYinVideo(DouYinBaseUploader):
|
|||||||
douyin_logger.info(_msg("🏃", f"小人开始搬运视频: {self.title}.mp4"))
|
douyin_logger.info(_msg("🏃", f"小人开始搬运视频: {self.title}.mp4"))
|
||||||
douyin_logger.info(_msg("🧭", "小人正在赶往上传主页"))
|
douyin_logger.info(_msg("🧭", "小人正在赶往上传主页"))
|
||||||
await page.wait_for_url("https://creator.douyin.com/creator-micro/content/upload")
|
await page.wait_for_url("https://creator.douyin.com/creator-micro/content/upload")
|
||||||
|
# wait_for_url 完成时上传页可能尚未渲染出文件 input(实测偶发),先等它挂载再 set_input_files
|
||||||
|
await page.wait_for_selector("div[class^='container'] input", state="attached", timeout=60000)
|
||||||
await page.locator("div[class^='container'] input").set_input_files(self.file_path)
|
await page.locator("div[class^='container'] input").set_input_files(self.file_path)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
Reference in New Issue
Block a user