From 9788647ede15f2b972c43adf8c648a8133443e5c Mon Sep 17 00:00:00 2001 From: wangshaoqing Date: Wed, 27 May 2026 15:36:22 +0800 Subject: [PATCH] Use shared Chrome debug port --- README.md | 6 +++++- XHS.py | 4 ++-- .../specs/2026-05-27-xhs-browser-feed-download-design.md | 2 +- login_xhs.py | 4 ++-- test_login_xhs.py | 8 ++++---- test_xhs.py | 8 ++++---- 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 4f861d7..122501c 100644 --- a/README.md +++ b/README.md @@ -36,11 +36,15 @@ pip install requests DrissionPage ### 步骤 1:启动 Chrome 并手动登录 +如果你已经通过抖音项目启动了调试端口为 `9223` 的 Chrome,可以直接在那个 Chrome 里打开并登录小红书,不需要再运行 `login_xhs.py`。 + +如果还没有可复用的 Chrome,再运行: + ```bash ./.venv/bin/python login_xhs.py ``` -脚本会打开 `https://www.xiaohongshu.com/explore`。请在打开的浏览器里完成登录;如果出现验证码,也需要手动处理。 +脚本会用默认端口 `9223` 打开 `https://www.xiaohongshu.com/explore`。请在打开的浏览器里完成登录;如果出现验证码,也需要手动处理。 ### 步骤 2:下载发现页视频 diff --git a/XHS.py b/XHS.py index abfc706..63c490a 100644 --- a/XHS.py +++ b/XHS.py @@ -13,7 +13,7 @@ from typing import Any from urllib.parse import urljoin DEFAULT_EXPLORE_URL = "https://www.xiaohongshu.com/explore" -DEFAULT_BROWSER_PORT = 9224 +DEFAULT_BROWSER_PORT = 9223 DEFAULT_OUTPUT_DIR = Path("video") LISTEN_TARGET = "/api/sns/web/v1/feed" MAX_FILENAME_BYTES = 240 @@ -533,7 +533,7 @@ def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description="附着到已登录小红书 Chrome,监听 feed 响应并下载视频") parser.add_argument("--max-videos", type=int, default=10, help="最多下载视频数量,默认 10") parser.add_argument("--output-dir", default=str(DEFAULT_OUTPUT_DIR), help="视频保存目录,默认 video") - parser.add_argument("--browser-port", type=int, default=DEFAULT_BROWSER_PORT, help="Chrome 调试端口,默认 9224") + parser.add_argument("--browser-port", type=int, default=DEFAULT_BROWSER_PORT, help="Chrome 调试端口,默认 9223") parser.add_argument("--timeout", type=int, default=20, help="等待单次 feed 响应的秒数,默认 20") parser.add_argument("--start-url", default=DEFAULT_EXPLORE_URL, help="打开或刷新使用的小红书页面") parser.add_argument("--use-current-page", action="store_true", help="使用浏览器当前页面,不强制打开发现页") diff --git a/docs/superpowers/specs/2026-05-27-xhs-browser-feed-download-design.md b/docs/superpowers/specs/2026-05-27-xhs-browser-feed-download-design.md index 38cb19a..99cb297 100644 --- a/docs/superpowers/specs/2026-05-27-xhs-browser-feed-download-design.md +++ b/docs/superpowers/specs/2026-05-27-xhs-browser-feed-download-design.md @@ -31,7 +31,7 @@ The tool mirrors the existing Douyin project pattern: ```bash python3 login_xhs.py python3 XHS.py --max-videos 10 -python3 XHS.py --browser-port 9224 --max-videos 20 --output-dir video +python3 XHS.py --browser-port 9334 --max-videos 20 --output-dir video ``` ## Error Handling diff --git a/login_xhs.py b/login_xhs.py index df0e077..8ec0c84 100644 --- a/login_xhs.py +++ b/login_xhs.py @@ -9,7 +9,7 @@ from pathlib import Path DEFAULT_START_URL = "https://www.xiaohongshu.com/explore" DEFAULT_CHROME_PATH = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" -DEFAULT_BROWSER_PORT = 9224 +DEFAULT_BROWSER_PORT = 9223 DEFAULT_PROFILE_DIR = Path(".xhs-chrome-profile") @@ -50,7 +50,7 @@ def build_parser() -> argparse.ArgumentParser: "--browser-port", type=int, default=DEFAULT_BROWSER_PORT, - help="Chrome 调试端口,默认 9224", + help="Chrome 调试端口,默认 9223", ) parser.add_argument("--start-url", default=DEFAULT_START_URL, help="启动后打开的小红书页面 URL") return parser diff --git a/test_login_xhs.py b/test_login_xhs.py index bb191b1..b497c70 100644 --- a/test_login_xhs.py +++ b/test_login_xhs.py @@ -13,7 +13,7 @@ class LoginXhsModuleTests(unittest.TestCase): command = module.build_login_command( chrome_path="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", profile_dir=Path("/tmp/xhs-profile"), - browser_port=9224, + browser_port=9223, start_url="https://www.xiaohongshu.com/explore", ) self.assertEqual( @@ -24,7 +24,7 @@ class LoginXhsModuleTests(unittest.TestCase): "/Applications/Google Chrome.app", "--args", "--user-data-dir=/tmp/xhs-profile", - "--remote-debugging-port=9224", + "--remote-debugging-port=9223", "https://www.xiaohongshu.com/explore", ], ) @@ -32,7 +32,7 @@ class LoginXhsModuleTests(unittest.TestCase): def test_build_parser_uses_expected_defaults(self) -> None: module = importlib.import_module("login_xhs") args = module.build_parser().parse_args([]) - self.assertEqual(args.browser_port, 9224) + self.assertEqual(args.browser_port, 9223) self.assertEqual(args.chrome_path, module.DEFAULT_CHROME_PATH) self.assertEqual(args.start_url, module.DEFAULT_START_URL) @@ -79,7 +79,7 @@ class LoginXhsModuleTests(unittest.TestCase): ) self.assertEqual(exit_code, 0) self.assertIn("./.venv/bin/python XHS.py", stdout.getvalue()) - self.assertNotIn("--browser-port 9224", stdout.getvalue()) + self.assertNotIn("--browser-port 9223", stdout.getvalue()) def test_main_returns_error_when_chrome_path_missing(self) -> None: module = importlib.import_module("login_xhs") diff --git a/test_xhs.py b/test_xhs.py index d3e0893..cd1736c 100644 --- a/test_xhs.py +++ b/test_xhs.py @@ -153,7 +153,7 @@ class XhsModuleTests(unittest.TestCase): def test_build_browser_address_from_port(self) -> None: module = importlib.import_module("XHS") - self.assertEqual(module.build_browser_address(9224), "127.0.0.1:9224") + self.assertEqual(module.build_browser_address(9223), "127.0.0.1:9223") self.assertIsNone(module.build_browser_address(None)) def test_ensure_browser_debug_port_ready_accepts_open_port(self) -> None: @@ -162,14 +162,14 @@ class XhsModuleTests(unittest.TestCase): connection.__enter__.return_value = connection connection.__exit__.return_value = False with mock.patch.object(module.socket, "create_connection", return_value=connection) as mocked_connect: - module.ensure_browser_debug_port_ready(9224) + module.ensure_browser_debug_port_ready(9223) mocked_connect.assert_called_once() def test_ensure_browser_debug_port_ready_rejects_closed_port(self) -> None: module = importlib.import_module("XHS") with mock.patch.object(module.socket, "create_connection", side_effect=OSError("boom")): with self.assertRaisesRegex(RuntimeError, "login_xhs.py"): - module.ensure_browser_debug_port_ready(9224) + module.ensure_browser_debug_port_ready(9223) def test_extract_feed_payload_uses_dict_body(self) -> None: module = importlib.import_module("XHS") @@ -189,7 +189,7 @@ class XhsModuleTests(unittest.TestCase): args = module.build_parser().parse_args([]) self.assertEqual(args.max_videos, 10) self.assertEqual(args.output_dir, "video") - self.assertEqual(args.browser_port, 9224) + self.assertEqual(args.browser_port, 9223) self.assertEqual(args.timeout, 20) self.assertEqual(args.start_url, module.DEFAULT_EXPLORE_URL) self.assertFalse(args.use_current_page)