dp-cli 0.5.0__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dp_cli-0.5.0 → dp_cli-0.6.0}/PKG-INFO +14 -13
- {dp_cli-0.5.0 → dp_cli-0.6.0}/README.md +13 -12
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/bridge_manager.py +5 -4
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/browser.py +33 -13
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/session.py +60 -5
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli.egg-info/PKG-INFO +14 -13
- {dp_cli-0.5.0 → dp_cli-0.6.0}/pyproject.toml +1 -1
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/__init__.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/bridge.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/__init__.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/_utils.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/element.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/keyboard.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/misc.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/network.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/page.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/record.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/snapshot_cmd.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/storage.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/commands/tab.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/locators/__init__.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/locators/playwright.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/locators/pw_js.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/main.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/output.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/recorder.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/snapshot/__init__.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/snapshot/a11y.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/snapshot/clickable.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/snapshot/clickable_js.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/snapshot/extract.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/snapshot/js_scripts.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/snapshot/utils.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli/stealth.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli.egg-info/SOURCES.txt +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli.egg-info/dependency_links.txt +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli.egg-info/entry_points.txt +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli.egg-info/requires.txt +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/dp_cli.egg-info/top_level.txt +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/setup.cfg +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/tests/test_bridge_integration.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/tests/test_bridge_manager.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/tests/test_clickable.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/tests/test_pw_locator.py +0 -0
- {dp_cli-0.5.0 → dp_cli-0.6.0}/tests/test_resolve_locator.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dp-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: A powerful CLI for DrissionPage — browser automation, structured data extraction, network listening and more.
|
|
5
5
|
License: BSD-3-Clause
|
|
6
6
|
Project-URL: Homepage, https://github.com/mofanx/dp-cli
|
|
@@ -26,7 +26,7 @@ A powerful CLI for [DrissionPage](https://github.com/g1879/DrissionPage) — bro
|
|
|
26
26
|
## Features
|
|
27
27
|
|
|
28
28
|
- **Anti-detection by default** — not based on webdriver, `navigator.webdriver` is `false`
|
|
29
|
-
- **Reuse your own browser** — `--auto-connect` (Chrome 144+, no CLI flag needed) or `--port`
|
|
29
|
+
- **Reuse your own browser** — `--auto-connect` (Chrome/Edge 144+, no CLI flag needed) or `--port`
|
|
30
30
|
- **Hybrid snapshot** — a11y tree + Vimium-style clickable detection, catches icon-only buttons
|
|
31
31
|
and custom menu items the a11y tree misses; every element gets an `[N]` ref with
|
|
32
32
|
confidence markers (`⚡` medium, `?` low)
|
|
@@ -64,25 +64,26 @@ dp open https://example.com --port 9222
|
|
|
64
64
|
dp snapshot
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
## Connect to a Normally-Launched Chrome (Chrome 144+)
|
|
67
|
+
## Connect to a Normally-Launched Chrome/Edge (Chrome/Edge 144+)
|
|
68
68
|
|
|
69
|
-
No `--remote-debugging-port` required. Chrome 144+ exposes opt-in remote debugging
|
|
70
|
-
via `chrome://inspect
|
|
69
|
+
No `--remote-debugging-port` required. Chrome/Edge 144+ exposes opt-in remote debugging
|
|
70
|
+
via `chrome://inspect` (Chrome) or `edge://inspect/#devices` (Edge):
|
|
71
71
|
|
|
72
|
-
1. Open your Chrome as usual (no special flags)
|
|
73
|
-
2. Visit `chrome://inspect/#remote-debugging`
|
|
72
|
+
1. Open your Chrome or Edge as usual (no special flags)
|
|
73
|
+
2. Visit `chrome://inspect/#remote-debugging` (Chrome) or `edge://inspect/#devices` (Edge)
|
|
74
74
|
3. Check **"Allow remote debugging for this browser instance"**
|
|
75
75
|
4. Run `dp open --auto-connect`
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
|
-
dp open --auto-connect #
|
|
79
|
-
dp open --auto-connect --channel
|
|
78
|
+
dp open --auto-connect # auto channel: sniffs Chrome stable → Edge stable
|
|
79
|
+
dp open --auto-connect --channel edge # force Edge stable
|
|
80
|
+
dp open --auto-connect --channel beta # Chrome beta
|
|
80
81
|
dp open --auto-connect --probe-dir ~/my-profile # custom user-data-dir
|
|
81
82
|
```
|
|
82
83
|
|
|
83
84
|
### How it works
|
|
84
85
|
|
|
85
|
-
Chrome 144+ in this mode exposes **only** a browser-level WebSocket and omits the HTTP
|
|
86
|
+
Chrome/Edge 144+ in this mode exposes **only** a browser-level WebSocket and omits the HTTP
|
|
86
87
|
REST API (`/json`, `/json/version`, ...) that DrissionPage / puppeteer / Playwright
|
|
87
88
|
depend on. `dp-cli` transparently handles this:
|
|
88
89
|
|
|
@@ -95,14 +96,14 @@ depend on. `dp-cli` transparently handles this:
|
|
|
95
96
|
4. Points DrissionPage at the bridge. Subsequent `dp` commands reuse the same bridge.
|
|
96
97
|
|
|
97
98
|
The bridge subprocess and its port are tracked in the session file; `dp close` stops
|
|
98
|
-
the bridge automatically and never quits your
|
|
99
|
+
the bridge automatically and never quits your browser (it's your browser, not dp's).
|
|
99
100
|
|
|
100
101
|
### Caveats
|
|
101
102
|
|
|
102
|
-
- Chrome always shows an **"Allow remote debugging"** dialog per new WebSocket client.
|
|
103
|
+
- Chrome/Edge always shows an **"Allow remote debugging"** dialog per new WebSocket client.
|
|
103
104
|
Since bridge maintains one WebSocket and dp commands share it, you confirm at most
|
|
104
105
|
once per `dp open --auto-connect`.
|
|
105
|
-
- Works with whatever profile Chrome is actually using — same cookies, logins, history.
|
|
106
|
+
- Works with whatever profile Chrome/Edge is actually using — same cookies, logins, history.
|
|
106
107
|
- Classic `--remote-debugging-port=9222` mode still works unchanged via `dp open --port 9222`.
|
|
107
108
|
|
|
108
109
|
## Hybrid Snapshot (a11y + Vimium-style)
|
|
@@ -5,7 +5,7 @@ A powerful CLI for [DrissionPage](https://github.com/g1879/DrissionPage) — bro
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Anti-detection by default** — not based on webdriver, `navigator.webdriver` is `false`
|
|
8
|
-
- **Reuse your own browser** — `--auto-connect` (Chrome 144+, no CLI flag needed) or `--port`
|
|
8
|
+
- **Reuse your own browser** — `--auto-connect` (Chrome/Edge 144+, no CLI flag needed) or `--port`
|
|
9
9
|
- **Hybrid snapshot** — a11y tree + Vimium-style clickable detection, catches icon-only buttons
|
|
10
10
|
and custom menu items the a11y tree misses; every element gets an `[N]` ref with
|
|
11
11
|
confidence markers (`⚡` medium, `?` low)
|
|
@@ -43,25 +43,26 @@ dp open https://example.com --port 9222
|
|
|
43
43
|
dp snapshot
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
## Connect to a Normally-Launched Chrome (Chrome 144+)
|
|
46
|
+
## Connect to a Normally-Launched Chrome/Edge (Chrome/Edge 144+)
|
|
47
47
|
|
|
48
|
-
No `--remote-debugging-port` required. Chrome 144+ exposes opt-in remote debugging
|
|
49
|
-
via `chrome://inspect
|
|
48
|
+
No `--remote-debugging-port` required. Chrome/Edge 144+ exposes opt-in remote debugging
|
|
49
|
+
via `chrome://inspect` (Chrome) or `edge://inspect/#devices` (Edge):
|
|
50
50
|
|
|
51
|
-
1. Open your Chrome as usual (no special flags)
|
|
52
|
-
2. Visit `chrome://inspect/#remote-debugging`
|
|
51
|
+
1. Open your Chrome or Edge as usual (no special flags)
|
|
52
|
+
2. Visit `chrome://inspect/#remote-debugging` (Chrome) or `edge://inspect/#devices` (Edge)
|
|
53
53
|
3. Check **"Allow remote debugging for this browser instance"**
|
|
54
54
|
4. Run `dp open --auto-connect`
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
|
-
dp open --auto-connect #
|
|
58
|
-
dp open --auto-connect --channel
|
|
57
|
+
dp open --auto-connect # auto channel: sniffs Chrome stable → Edge stable
|
|
58
|
+
dp open --auto-connect --channel edge # force Edge stable
|
|
59
|
+
dp open --auto-connect --channel beta # Chrome beta
|
|
59
60
|
dp open --auto-connect --probe-dir ~/my-profile # custom user-data-dir
|
|
60
61
|
```
|
|
61
62
|
|
|
62
63
|
### How it works
|
|
63
64
|
|
|
64
|
-
Chrome 144+ in this mode exposes **only** a browser-level WebSocket and omits the HTTP
|
|
65
|
+
Chrome/Edge 144+ in this mode exposes **only** a browser-level WebSocket and omits the HTTP
|
|
65
66
|
REST API (`/json`, `/json/version`, ...) that DrissionPage / puppeteer / Playwright
|
|
66
67
|
depend on. `dp-cli` transparently handles this:
|
|
67
68
|
|
|
@@ -74,14 +75,14 @@ depend on. `dp-cli` transparently handles this:
|
|
|
74
75
|
4. Points DrissionPage at the bridge. Subsequent `dp` commands reuse the same bridge.
|
|
75
76
|
|
|
76
77
|
The bridge subprocess and its port are tracked in the session file; `dp close` stops
|
|
77
|
-
the bridge automatically and never quits your
|
|
78
|
+
the bridge automatically and never quits your browser (it's your browser, not dp's).
|
|
78
79
|
|
|
79
80
|
### Caveats
|
|
80
81
|
|
|
81
|
-
- Chrome always shows an **"Allow remote debugging"** dialog per new WebSocket client.
|
|
82
|
+
- Chrome/Edge always shows an **"Allow remote debugging"** dialog per new WebSocket client.
|
|
82
83
|
Since bridge maintains one WebSocket and dp commands share it, you confirm at most
|
|
83
84
|
once per `dp open --auto-connect`.
|
|
84
|
-
- Works with whatever profile Chrome is actually using — same cookies, logins, history.
|
|
85
|
+
- Works with whatever profile Chrome/Edge is actually using — same cookies, logins, history.
|
|
85
86
|
- Classic `--remote-debugging-port=9222` mode still works unchanged via `dp open --port 9222`.
|
|
86
87
|
|
|
87
88
|
## Hybrid Snapshot (a11y + Vimium-style)
|
|
@@ -94,9 +94,10 @@ def start_bridge(user_data_dir: str | os.PathLike,
|
|
|
94
94
|
|
|
95
95
|
# 立即提示用户:bridge 正在连接;若 Chrome 弹出授权框请点击。
|
|
96
96
|
# 写 stderr 避免污染 stdout 的 JSON 输出。
|
|
97
|
-
print('[dp] 正在启动 bridge
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
print('[dp] 正在启动 bridge 并连接浏览器(Chrome/Edge)…',
|
|
98
|
+
file=sys.stderr, flush=True)
|
|
99
|
+
print('[dp] 💡 若浏览器弹出 "Allow remote debugging" 对话框,'
|
|
100
|
+
'请切到浏览器窗口点击 "Allow"(后续命令会自动复用连接)',
|
|
100
101
|
file=sys.stderr, flush=True)
|
|
101
102
|
|
|
102
103
|
# 异步读 stderr,方便 timeout 时回显给用户
|
|
@@ -143,7 +144,7 @@ def start_bridge(user_data_dir: str | os.PathLike,
|
|
|
143
144
|
proc.terminate()
|
|
144
145
|
raise RuntimeError(
|
|
145
146
|
f'bridge 启动超时 ({ready_timeout}s)。\n'
|
|
146
|
-
f'
|
|
147
|
+
f'若是首次连接:请把浏览器窗口(Chrome/Edge)切到前台,点击弹出的'
|
|
147
148
|
f' "Allow remote debugging for this browser instance" 对话框。\n'
|
|
148
149
|
f'当前 bridge stderr:\n{_collect_stderr()}'
|
|
149
150
|
)
|
|
@@ -7,7 +7,8 @@ import click
|
|
|
7
7
|
from dp_cli.session import (get_browser, close_browser, list_sessions,
|
|
8
8
|
delete_session, load_session, save_session,
|
|
9
9
|
discover_port_from_profile,
|
|
10
|
-
default_user_data_dir_for_channel
|
|
10
|
+
default_user_data_dir_for_channel,
|
|
11
|
+
sniff_auto_user_data_dir)
|
|
11
12
|
from dp_cli.output import ok, error, format_page_info
|
|
12
13
|
from dp_cli.commands._utils import session_option, _get_page, normalize_url
|
|
13
14
|
from dp_cli.stealth import apply_stealth, PRESETS, DEFAULT_UA
|
|
@@ -24,11 +25,14 @@ def register(cli):
|
|
|
24
25
|
@click.option('--proxy', default=None, help='代理服务器,如 http://127.0.0.1:7890')
|
|
25
26
|
@click.option('--port', type=int, default=None, help='连接指定端口的已有浏览器实例')
|
|
26
27
|
@click.option('--auto-connect', '-a', is_flag=True,
|
|
27
|
-
help='从用户常规启动的 Chrome 读取 DevToolsActivePort 自动发现端口'
|
|
28
|
-
'(需 Chrome 144+,用户在 chrome://inspect/#remote-debugging
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
help='从用户常规启动的 Chrome/Edge 读取 DevToolsActivePort 自动发现端口'
|
|
29
|
+
'(需 Chrome/Edge 144+,用户在 chrome://inspect/#remote-debugging 或 '
|
|
30
|
+
'edge://inspect/#devices 启用)')
|
|
31
|
+
@click.option('--channel',
|
|
32
|
+
type=click.Choice(['auto', 'stable', 'beta', 'dev', 'canary', 'chromium', 'edge']),
|
|
33
|
+
default='auto', show_default=True,
|
|
34
|
+
help='配合 --auto-connect 使用,定位默认 user-data-dir;'
|
|
35
|
+
'auto = 依次嗅探 chrome stable → edge stable,取首个含 DevToolsActivePort 的目录')
|
|
32
36
|
@click.option('--probe-dir', 'probe_dir', default=None,
|
|
33
37
|
help='配合 --auto-connect 使用,显式指定要探测的 user-data-dir '
|
|
34
38
|
'(覆盖 --channel 的默认路径)')
|
|
@@ -46,14 +50,16 @@ def register(cli):
|
|
|
46
50
|
dp open --port 9222
|
|
47
51
|
|
|
48
52
|
\b
|
|
49
|
-
【复用用户自己的浏览器 - 方式 B:--auto-connect(Chrome 144+ 推荐)】
|
|
50
|
-
无需特殊启动参数,正常打开 Chrome 即可:
|
|
51
|
-
1.
|
|
53
|
+
【复用用户自己的浏览器 - 方式 B:--auto-connect(Chrome/Edge 144+ 推荐)】
|
|
54
|
+
无需特殊启动参数,正常打开 Chrome 或 Edge 即可:
|
|
55
|
+
1. 打开浏览器:
|
|
56
|
+
- Chrome:访问 chrome://inspect/#remote-debugging
|
|
57
|
+
- Edge: 访问 edge://inspect/#devices
|
|
52
58
|
2. 勾选 "Allow remote debugging for this browser instance"
|
|
53
|
-
3. dp open --auto-connect
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
3. dp open --auto-connect # 默认 auto:先嗅探 Chrome,再 Edge
|
|
60
|
+
dp open --auto-connect --channel edge # 强制使用 Edge stable
|
|
61
|
+
dp open --auto-connect --channel beta # 使用 Chrome beta
|
|
62
|
+
dp open --auto-connect --probe-dir ~/my-profile # 自定义 profile
|
|
57
63
|
|
|
58
64
|
\b
|
|
59
65
|
【dp 自动管理浏览器】
|
|
@@ -83,6 +89,20 @@ def register(cli):
|
|
|
83
89
|
return
|
|
84
90
|
if probe_dir:
|
|
85
91
|
dir_to_probe = Path(probe_dir).expanduser()
|
|
92
|
+
elif channel == 'auto':
|
|
93
|
+
# 自动嗅探:chrome stable → edge stable,取首个含 DevToolsActivePort 的目录
|
|
94
|
+
hit, diag = sniff_auto_user_data_dir()
|
|
95
|
+
if hit is None:
|
|
96
|
+
detail = '\n'.join(f' - {ch:7s} {p} [{reason}]'
|
|
97
|
+
for ch, p, reason in diag)
|
|
98
|
+
error('自动嗅探未找到含 DevToolsActivePort 的 user-data-dir。\n'
|
|
99
|
+
'请先在 Chrome (chrome://inspect/#remote-debugging) 或 '
|
|
100
|
+
'Edge (edge://inspect/#devices) 启用远程调试,\n'
|
|
101
|
+
'或用 --channel/--probe-dir 显式指定。\n'
|
|
102
|
+
f'嗅探记录:\n{detail}',
|
|
103
|
+
code='PROFILE_NOT_FOUND')
|
|
104
|
+
return
|
|
105
|
+
dir_to_probe = hit
|
|
86
106
|
else:
|
|
87
107
|
dir_to_probe = default_user_data_dir_for_channel(channel)
|
|
88
108
|
if not dir_to_probe:
|
|
@@ -84,9 +84,9 @@ def _detect_headless(port: int) -> bool:
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
def default_user_data_dir_for_channel(channel: str = 'stable') -> Path | None:
|
|
87
|
-
"""返回指定 channel 的 Chrome 默认 user-data-dir。
|
|
87
|
+
"""返回指定 channel 的 Chrome/Edge 默认 user-data-dir。
|
|
88
88
|
|
|
89
|
-
:param channel: stable / beta / dev / canary / chromium
|
|
89
|
+
:param channel: stable / beta / dev / canary / chromium / edge
|
|
90
90
|
:return: 用户数据目录 Path;不存在时返回 None
|
|
91
91
|
"""
|
|
92
92
|
home = Path.home()
|
|
@@ -98,6 +98,7 @@ def default_user_data_dir_for_channel(channel: str = 'stable') -> Path | None:
|
|
|
98
98
|
'dev': [home / '.config' / 'google-chrome-unstable'],
|
|
99
99
|
'canary': [home / '.config' / 'google-chrome-canary'],
|
|
100
100
|
'chromium': [home / '.config' / 'chromium'],
|
|
101
|
+
'edge': [home / '.config' / 'microsoft-edge'],
|
|
101
102
|
}
|
|
102
103
|
elif sys.platform == 'darwin':
|
|
103
104
|
base = home / 'Library' / 'Application Support'
|
|
@@ -107,6 +108,7 @@ def default_user_data_dir_for_channel(channel: str = 'stable') -> Path | None:
|
|
|
107
108
|
'dev': [base / 'Google' / 'Chrome Dev'],
|
|
108
109
|
'canary': [base / 'Google' / 'Chrome Canary'],
|
|
109
110
|
'chromium': [base / 'Chromium'],
|
|
111
|
+
'edge': [base / 'Microsoft Edge'],
|
|
110
112
|
}
|
|
111
113
|
elif sys.platform.startswith('win'):
|
|
112
114
|
local = Path(os.environ.get('LOCALAPPDATA', home / 'AppData' / 'Local'))
|
|
@@ -116,6 +118,7 @@ def default_user_data_dir_for_channel(channel: str = 'stable') -> Path | None:
|
|
|
116
118
|
'dev': [local / 'Google' / 'Chrome Dev' / 'User Data'],
|
|
117
119
|
'canary': [local / 'Google' / 'Chrome SxS' / 'User Data'],
|
|
118
120
|
'chromium': [local / 'Chromium' / 'User Data'],
|
|
121
|
+
'edge': [local / 'Microsoft' / 'Edge' / 'User Data'],
|
|
119
122
|
}
|
|
120
123
|
|
|
121
124
|
for p in candidates.get(channel, []):
|
|
@@ -124,6 +127,56 @@ def default_user_data_dir_for_channel(channel: str = 'stable') -> Path | None:
|
|
|
124
127
|
return None
|
|
125
128
|
|
|
126
129
|
|
|
130
|
+
# --auto-connect 不传 --channel 时的嗅探顺序:先 Chrome stable,再 Edge stable
|
|
131
|
+
_AUTO_SNIFF_CHANNELS = ('stable', 'edge')
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _is_port_alive(port: int, timeout: float = 0.3) -> bool:
|
|
135
|
+
"""轻量 TCP 探活:能 connect 上即视为活的。"""
|
|
136
|
+
import socket
|
|
137
|
+
try:
|
|
138
|
+
with socket.create_connection(('127.0.0.1', port), timeout=timeout):
|
|
139
|
+
return True
|
|
140
|
+
except Exception:
|
|
141
|
+
return False
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def sniff_auto_user_data_dir() -> tuple[Path | None, list[tuple[str, Path, str]]]:
|
|
145
|
+
"""auto channel:按 _AUTO_SNIFF_CHANNELS 顺序查找首个含可用 DevToolsActivePort 的目录。
|
|
146
|
+
|
|
147
|
+
会校验端口实际可连通,避免命中浏览器已关闭后残留的陈旧文件。
|
|
148
|
+
|
|
149
|
+
:return: (命中目录或 None, 诊断记录列表)
|
|
150
|
+
诊断记录每项为 (channel, path, reason),reason 取值:
|
|
151
|
+
- 'hit' 命中(文件存在且端口活)
|
|
152
|
+
- 'no_dir' 用户数据目录不存在
|
|
153
|
+
- 'no_port' 目录存在但缺 DevToolsActivePort
|
|
154
|
+
- 'stale' DevToolsActivePort 存在但端口不通(陈旧残留)
|
|
155
|
+
- 'bad_file' DevToolsActivePort 文件解析失败
|
|
156
|
+
"""
|
|
157
|
+
diag: list[tuple[str, Path, str]] = []
|
|
158
|
+
for ch in _AUTO_SNIFF_CHANNELS:
|
|
159
|
+
p = default_user_data_dir_for_channel(ch)
|
|
160
|
+
if p is None:
|
|
161
|
+
diag.append((ch, Path('<not found>'), 'no_dir'))
|
|
162
|
+
continue
|
|
163
|
+
f = p / 'DevToolsActivePort'
|
|
164
|
+
if not f.exists():
|
|
165
|
+
diag.append((ch, p, 'no_port'))
|
|
166
|
+
continue
|
|
167
|
+
try:
|
|
168
|
+
port = discover_port_from_profile(p)
|
|
169
|
+
except (FileNotFoundError, ValueError):
|
|
170
|
+
diag.append((ch, p, 'bad_file'))
|
|
171
|
+
continue
|
|
172
|
+
if not _is_port_alive(port):
|
|
173
|
+
diag.append((ch, p, 'stale'))
|
|
174
|
+
continue
|
|
175
|
+
diag.append((ch, p, 'hit'))
|
|
176
|
+
return p, diag
|
|
177
|
+
return None, diag
|
|
178
|
+
|
|
179
|
+
|
|
127
180
|
def discover_port_from_profile(user_data_dir: str | os.PathLike) -> int:
|
|
128
181
|
"""从 Chrome user-data-dir 的 DevToolsActivePort 文件读取端口号。
|
|
129
182
|
|
|
@@ -137,9 +190,11 @@ def discover_port_from_profile(user_data_dir: str | os.PathLike) -> int:
|
|
|
137
190
|
if not p.exists():
|
|
138
191
|
raise FileNotFoundError(
|
|
139
192
|
f'未找到 {p}。请确认:\n'
|
|
140
|
-
f' 1. 浏览器正在运行,且
|
|
141
|
-
f' 2. 已在地址栏打开 chrome://inspect/#remote-debugging
|
|
142
|
-
f'
|
|
193
|
+
f' 1. 浏览器正在运行,且 user-data-dir 匹配:{user_data_dir}\n'
|
|
194
|
+
f' 2. 已在地址栏打开 chrome://inspect/#remote-debugging\n'
|
|
195
|
+
f' (Edge 用 edge://inspect/#devices)并点击\n'
|
|
196
|
+
f' "Allow remote debugging for this browser instance"\n'
|
|
197
|
+
f' (需 Chrome/Edge 144+)'
|
|
143
198
|
)
|
|
144
199
|
lines = [l.strip() for l in p.read_text(encoding='utf-8').splitlines() if l.strip()]
|
|
145
200
|
if not lines:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dp-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: A powerful CLI for DrissionPage — browser automation, structured data extraction, network listening and more.
|
|
5
5
|
License: BSD-3-Clause
|
|
6
6
|
Project-URL: Homepage, https://github.com/mofanx/dp-cli
|
|
@@ -26,7 +26,7 @@ A powerful CLI for [DrissionPage](https://github.com/g1879/DrissionPage) — bro
|
|
|
26
26
|
## Features
|
|
27
27
|
|
|
28
28
|
- **Anti-detection by default** — not based on webdriver, `navigator.webdriver` is `false`
|
|
29
|
-
- **Reuse your own browser** — `--auto-connect` (Chrome 144+, no CLI flag needed) or `--port`
|
|
29
|
+
- **Reuse your own browser** — `--auto-connect` (Chrome/Edge 144+, no CLI flag needed) or `--port`
|
|
30
30
|
- **Hybrid snapshot** — a11y tree + Vimium-style clickable detection, catches icon-only buttons
|
|
31
31
|
and custom menu items the a11y tree misses; every element gets an `[N]` ref with
|
|
32
32
|
confidence markers (`⚡` medium, `?` low)
|
|
@@ -64,25 +64,26 @@ dp open https://example.com --port 9222
|
|
|
64
64
|
dp snapshot
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
## Connect to a Normally-Launched Chrome (Chrome 144+)
|
|
67
|
+
## Connect to a Normally-Launched Chrome/Edge (Chrome/Edge 144+)
|
|
68
68
|
|
|
69
|
-
No `--remote-debugging-port` required. Chrome 144+ exposes opt-in remote debugging
|
|
70
|
-
via `chrome://inspect
|
|
69
|
+
No `--remote-debugging-port` required. Chrome/Edge 144+ exposes opt-in remote debugging
|
|
70
|
+
via `chrome://inspect` (Chrome) or `edge://inspect/#devices` (Edge):
|
|
71
71
|
|
|
72
|
-
1. Open your Chrome as usual (no special flags)
|
|
73
|
-
2. Visit `chrome://inspect/#remote-debugging`
|
|
72
|
+
1. Open your Chrome or Edge as usual (no special flags)
|
|
73
|
+
2. Visit `chrome://inspect/#remote-debugging` (Chrome) or `edge://inspect/#devices` (Edge)
|
|
74
74
|
3. Check **"Allow remote debugging for this browser instance"**
|
|
75
75
|
4. Run `dp open --auto-connect`
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
|
-
dp open --auto-connect #
|
|
79
|
-
dp open --auto-connect --channel
|
|
78
|
+
dp open --auto-connect # auto channel: sniffs Chrome stable → Edge stable
|
|
79
|
+
dp open --auto-connect --channel edge # force Edge stable
|
|
80
|
+
dp open --auto-connect --channel beta # Chrome beta
|
|
80
81
|
dp open --auto-connect --probe-dir ~/my-profile # custom user-data-dir
|
|
81
82
|
```
|
|
82
83
|
|
|
83
84
|
### How it works
|
|
84
85
|
|
|
85
|
-
Chrome 144+ in this mode exposes **only** a browser-level WebSocket and omits the HTTP
|
|
86
|
+
Chrome/Edge 144+ in this mode exposes **only** a browser-level WebSocket and omits the HTTP
|
|
86
87
|
REST API (`/json`, `/json/version`, ...) that DrissionPage / puppeteer / Playwright
|
|
87
88
|
depend on. `dp-cli` transparently handles this:
|
|
88
89
|
|
|
@@ -95,14 +96,14 @@ depend on. `dp-cli` transparently handles this:
|
|
|
95
96
|
4. Points DrissionPage at the bridge. Subsequent `dp` commands reuse the same bridge.
|
|
96
97
|
|
|
97
98
|
The bridge subprocess and its port are tracked in the session file; `dp close` stops
|
|
98
|
-
the bridge automatically and never quits your
|
|
99
|
+
the bridge automatically and never quits your browser (it's your browser, not dp's).
|
|
99
100
|
|
|
100
101
|
### Caveats
|
|
101
102
|
|
|
102
|
-
- Chrome always shows an **"Allow remote debugging"** dialog per new WebSocket client.
|
|
103
|
+
- Chrome/Edge always shows an **"Allow remote debugging"** dialog per new WebSocket client.
|
|
103
104
|
Since bridge maintains one WebSocket and dp commands share it, you confirm at most
|
|
104
105
|
once per `dp open --auto-connect`.
|
|
105
|
-
- Works with whatever profile Chrome is actually using — same cookies, logins, history.
|
|
106
|
+
- Works with whatever profile Chrome/Edge is actually using — same cookies, logins, history.
|
|
106
107
|
- Classic `--remote-debugging-port=9222` mode still works unchanged via `dp open --port 9222`.
|
|
107
108
|
|
|
108
109
|
## Hybrid Snapshot (a11y + Vimium-style)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "dp-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.6.0"
|
|
8
8
|
description = "A powerful CLI for DrissionPage — browser automation, structured data extraction, network listening and more."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|