1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
| class CDPClipboardManager: """CDP 剪贴板操作管理器""" def __init__(self, ws, session_id): self.ws = ws self.session_id = session_id self._cmd_id = 0 async def _cmd(self, method, params=None): self._cmd_id += 1 msg = {"id": self._cmd_id, "method": method, "params": params or {}} if self.session_id: msg["sessionId"] = self.session_id await self.ws.send(json.dumps(msg)) async for resp in self.ws: data = json.loads(resp) if data.get("id") == self._cmd_id: return data.get("result", {}) async def grant_permissions(self, origin=None): """授予剪贴板读写权限""" params = {"permissions": [ {"name": "clipboard-read"}, {"name": "clipboard-write"} ]} if origin: params["origin"] = origin await self._cmd("Browser.grantPermissions", params) print("Clipboard permissions granted") async def read_text(self): """读取剪贴板文本""" result = await self._cmd("Runtime.evaluate", { "expression": """ (async () => { try { const t = await navigator.clipboard.readText(); return { ok: true, text: t }; } catch (e) { return { ok: false, error: e.message }; } })() """, "awaitPromise": True }) v = result.get("result", {}).get("value", {}) return v.get("text") if v.get("ok") else None async def write_text(self, text): """写入文本到剪贴板""" escaped = json.dumps(text) result = await self._cmd("Runtime.evaluate", { "expression": f""" (async () => {{ try {{ await navigator.clipboard.writeText({escaped}); return {{ ok: true }}; }} catch (e) {{ return {{ ok: false, error: e.message }}; }} }})() """, "awaitPromise": True }) v = result.get("result", {}).get("value", {}) return v.get("ok", False) async def copy_from_element(self, selector): """从页面元素复制文本""" result = await self._cmd("Runtime.evaluate", { "expression": f""" (async () => {{ const el = document.querySelector('{selector}'); if (!el) return {{ ok: false }}; const text = el.textContent || el.value || ''; await navigator.clipboard.writeText(text); return {{ ok: true, text: text }}; }})() """, "awaitPromise": True }) v = result.get("result", {}).get("value", {}) return v.get("text") if v.get("ok") else None async def paste_to_element(self, selector, text): """将文本粘贴到目标元素""" escaped = json.dumps(text) result = await self._cmd("Runtime.evaluate", { "expression": f""" (() => {{ const el = document.querySelector('{selector}'); if (!el) return false; el.focus(); const start = el.selectionStart || 0; const val = el.value || el.textContent || ''; el.value = val.slice(0, start) + {escaped} + val.slice(el.selectionEnd || 0); el.dispatchEvent(new Event('input', {{ bubbles: true }})); return true; }})() """ }) return result.get("result", {}).get("value", False) async def set_files(self, selector, file_paths): """通过 DOM.setFileInputFiles 设置文件""" result = await self._cmd("Runtime.evaluate", { "expression": f""" document.querySelector('{selector}'); """, "objectGroup": "file_input" }) obj_id = result.get("result", {}).get("objectId") if not obj_id: return False dom = await self._cmd("DOM.requestNode", {"objectId": obj_id}) node_id = dom.get("nodeId") if not node_id: return False await self._cmd("DOM.setFileInputFiles", { "nodeId": node_id, "files": [file_paths] if isinstance(file_paths, str) else file_paths }) return True
|