Files
GenericAgent/memory/tmwebdriver_sop.md

90 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TMWebDriver SOP
- 禁止import直接用web_scan/web_execute_js工具。本文件只记录特性和坑。
- 底层:`../TMWebDriver.py`通过Tampermonkey脚本接管用户浏览器保留登录态/Cookie
- 非Selenium/Playwright不需调试浏览器或新数据目录
- 支撑 `web_scan`(只读DOM) / `web_execute_js`(执行JS) 等高层工具
## 限制(isTrusted)
- JS dispatch的事件`isTrusted=false`,敏感操作(文件上传/部分按钮)会被浏览器拦截
- 文件上传JS无法填充`<input type=file>`必须ljqCtrl物理点击+Win32轮询文件对话框
- 流程SetForegroundWindow→ljqCtrl点上传按钮→FindWindow轮询对话框→输入路径→轮询关闭
- 元素→屏幕物理坐标(ljqCtrl点击前必算)JS一次取rect+窗口信息,公式:
- `physX = (screenX + rect中心x) * dpr``physY = (screenY + chromeH + rect中心y) * dpr`
- chromeH = outerHeight - innerHeightdpr = devicePixelRatio
- 注意screenX/Y也是CSS像素所有值先加后统一乘dpr
- 结论:读信息+普通操作用TMWebDriver文件上传等敏感操作需配合ljqCtrl
## 导航
- `web_scan` 仅读当前页不导航,切换网站用 `web_execute_js` + `location.href='url'`
## Google图搜
- class名混淆禁硬编码点击结果用 `[role=button]` div
- web_scan过滤边栏弹出后用JS文本`document.body.innerText`大图遍历img按`naturalWidth`最大取src
- "访问"链接遍历a找`textContent.includes('访问')`的href
- 缩略图:`img[src^="data:image"]`直接提取大图src可能截断用`return img.src`
## Chrome下载PDF
场景PDF链接在浏览器内预览而非下载
```js
fetch('PDF_URL').then(r=>r.blob()).then(b=>{
const a=document.createElement('a');
a.href=URL.createObjectURL(b);
a.download='filename.pdf';
a.click();
});
```
注意需同源或CORS允许跨域先导航到目标域再执行
## Chrome后台标签节流
- 后台标签中`setTimeout`被Chrome intensive throttling延迟到≥1min/次
- TM脚本中detect_newtab的轮询(`setTimeout 150ms × 10`)会超时
- 已修复移除TM脚本内轮询改由Python侧`get_session_dict()`前后对比检测新标签
- 同理TM脚本中任何后台逻辑都应避免依赖setTimeout轮询
## Cookie+CDP桥(tmwd_cdp_bridge扩展)
前提:需先安装`assets/tmwd_cdp_bridge/`扩展(含debugger权限)
触发ID`__ljq_ctrl`
### Cookie提取(含HttpOnly)
注入`id="__ljq_ctrl"`的div(无需data-cmd默认cookies)→扩展写回JSON到textContent
```js
const d=document.createElement('div');d.id='__ljq_ctrl';
document.body.appendChild(d);
await new Promise(r=>setTimeout(r,300));
return d.textContent; // {ok:true, data:[...]}
```
### CDP命令(任意Chrome DevTools Protocol)
```js
const d=document.createElement('div');d.id='__ljq_ctrl';
d.dataset.cmd='cdp'; d.dataset.method='Network.getCookies';
d.dataset.params=JSON.stringify({urls:[location.href]});
document.body.appendChild(d);
await new Promise(r=>setTimeout(r,500));
return d.textContent; // {ok:true, data:{...}}
```
- 可用任意CDP方法(Network/DOM/Page/Runtime等)参数通过data-params传JSON
- 每次调用会attach→sendCommand→detach debugger页面顶部会短暂显示调试提示
## 登录凭证autofill获取
检测simphtml.py已内置autofill检测`web_scan`输出的input会带`data-autofilled="true"`属性value显示为`⚠️受保护-读tmwebdriver_sop的autofill章节提取`(非真实值)
问题:`:-webkit-autofill`可探测autofill状态`input.value`为空Chrome安全保护需物理点击释放
突破PostMessage点击输入框触发释放
前置枚举Chrome主窗口标题匹配web_scan当前页标题不匹配则切换标签页避免点到后台tab
流程JS检查`:-webkit-autofill`→获取`getBoundingClientRect()*devicePixelRatio`→PostMessage发`WM_LBUTTONDOWN/UP``Chrome_RenderWidgetHostHWND`子窗口→读`value`
多个RenderWidgetHostHWND共存(NexonLauncher等非浏览器Chrome应用也有)必须EnumWindows按父窗口标题匹配目标页再取其子RenderWidget
平台Windows用PostMessagemacOS用CGEvent未测试
## 验证码/页面视觉截图
- 优先JS `canvas.toDataURL()` 直接拿base64验证码是canvas/img时最干净无需截屏
- 备选:`window.open(location.href,'_blank')` 前台开新标签→win32截图→完后close
- GM_openInTab在web_execute_js不可用非油猴上下文
- 浏览器无JS API切标签页只能开新的来保证前台
## 跨域iframe操控(postMessage中继)
- 跨域iframe的contentDocument不可访问web_execute_js只在顶层执行
- TM脚本已改造iframe内不return改为监听postMessage并eval执行+回传结果
- 顶层发送:`iframe.contentWindow.postMessage({type:'ljq_exec', id, code}, '*')`
- iframe回传`{type:'ljq_result', id, result}` 通过window.addEventListener('message')接收
- ⚠只能eval表达式不支持return/函数体包装,构造代码时注意
- 流程发postMessage→等→读window._ljqResults[id]获取结果
- 已验证读取iframe内DOM(document.title)、填写input均成功