Committed by
GitHub
feat: 增强反检测、修复发布流程、新增草稿保存与选择器集中管理
- 完善登录信息返回,登录后显示登录名与小红薯号 - 新增 selectors.py 集中管理 CSS 选择器,便于改版维护 - 屏蔽位置等权限弹窗,减少发布流程干扰 - 优化 Tags 点击逻辑,降低标签无法选中的概率 - 强化浏览器伪装(JS 伪装、CDP 真实交互、随机延迟),触发验证时自动重试一次 - 修复发布流程 4 个 bug(页面关闭、标签错位、换行丢失、标签重复) - Chrome 启动器增强、运行锁修复、长文发布与类型优化 - 新增保存草稿(暂存离开)功能
Showing
3 changed files
with
51 additions
and
0 deletions
| @@ -420,6 +420,19 @@ def cmd_click_publish(args: argparse.Namespace) -> None: | @@ -420,6 +420,19 @@ def cmd_click_publish(args: argparse.Namespace) -> None: | ||
| 420 | browser.close() | 420 | browser.close() |
| 421 | 421 | ||
| 422 | 422 | ||
| 423 | +def cmd_save_draft(args: argparse.Namespace) -> None: | ||
| 424 | + """保存为草稿(取消发布时调用)。""" | ||
| 425 | + from xhs.publish import save_as_draft | ||
| 426 | + | ||
| 427 | + browser, page = _connect_existing(args) | ||
| 428 | + try: | ||
| 429 | + save_as_draft(page) | ||
| 430 | + _output({"success": True, "status": "内容已保存到草稿箱"}) | ||
| 431 | + finally: | ||
| 432 | + browser.close_page(page) | ||
| 433 | + browser.close() | ||
| 434 | + | ||
| 435 | + | ||
| 423 | def cmd_long_article(args: argparse.Namespace) -> None: | 436 | def cmd_long_article(args: argparse.Namespace) -> None: |
| 424 | """长文模式:填写内容 + 一键排版,返回模板列表。""" | 437 | """长文模式:填写内容 + 一键排版,返回模板列表。""" |
| 425 | from xhs.publish_long_article import publish_long_article | 438 | from xhs.publish_long_article import publish_long_article |
| @@ -677,6 +690,10 @@ def build_parser() -> argparse.ArgumentParser: | @@ -677,6 +690,10 @@ def build_parser() -> argparse.ArgumentParser: | ||
| 677 | sub.add_argument("--content-file", required=True, help="描述内容文件路径") | 690 | sub.add_argument("--content-file", required=True, help="描述内容文件路径") |
| 678 | sub.set_defaults(func=cmd_next_step) | 691 | sub.set_defaults(func=cmd_next_step) |
| 679 | 692 | ||
| 693 | + # save-draft(保存草稿) | ||
| 694 | + sub = subparsers.add_parser("save-draft", help="保存为草稿(取消发布时使用)") | ||
| 695 | + sub.set_defaults(func=cmd_save_draft) | ||
| 696 | + | ||
| 680 | return parser | 697 | return parser |
| 681 | 698 | ||
| 682 | 699 |
| @@ -572,6 +572,16 @@ class Browser: | @@ -572,6 +572,16 @@ class Browser: | ||
| 572 | }, | 572 | }, |
| 573 | ) | 573 | ) |
| 574 | 574 | ||
| 575 | + # 拒绝权限弹窗(位置、通知等) | ||
| 576 | + import contextlib | ||
| 577 | + | ||
| 578 | + for perm in ("geolocation", "notifications", "midi", "camera", "microphone"): | ||
| 579 | + with contextlib.suppress(CDPError): | ||
| 580 | + self._cdp.send( | ||
| 581 | + "Browser.setPermission", | ||
| 582 | + {"permission": {"name": perm}, "setting": "denied"}, | ||
| 583 | + ) | ||
| 584 | + | ||
| 575 | # 启用必要的 domain | 585 | # 启用必要的 domain |
| 576 | page._send_session("Page.enable") | 586 | page._send_session("Page.enable") |
| 577 | page._send_session("DOM.enable") | 587 | page._send_session("DOM.enable") |
| @@ -121,6 +121,30 @@ def click_publish_button(page: Page) -> None: | @@ -121,6 +121,30 @@ def click_publish_button(page: Page) -> None: | ||
| 121 | logger.info("发布完成") | 121 | logger.info("发布完成") |
| 122 | 122 | ||
| 123 | 123 | ||
| 124 | +def save_as_draft(page: Page) -> None: | ||
| 125 | + """点击「暂存离开」按钮保存草稿。""" | ||
| 126 | + clicked = page.evaluate( | ||
| 127 | + """ | ||
| 128 | + (() => { | ||
| 129 | + const buttons = document.querySelectorAll('button.custom-button'); | ||
| 130 | + for (const btn of buttons) { | ||
| 131 | + if (btn.textContent.trim() === '暂存离开') { | ||
| 132 | + btn.click(); | ||
| 133 | + return true; | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + return false; | ||
| 137 | + })() | ||
| 138 | + """ | ||
| 139 | + ) | ||
| 140 | + if clicked: | ||
| 141 | + time.sleep(2) | ||
| 142 | + logger.info("已点击「暂存离开」,内容已保存到草稿箱") | ||
| 143 | + else: | ||
| 144 | + logger.warning("未找到「暂存离开」按钮") | ||
| 145 | + raise PublishError("未找到「暂存离开」按钮") | ||
| 146 | + | ||
| 147 | + | ||
| 124 | # ========== 页面导航 ========== | 148 | # ========== 页面导航 ========== |
| 125 | 149 | ||
| 126 | 150 |
-
Please register or login to post a comment