Files
GenericAgent/memory/tmwebdriver_sop.md

5.1 KiB
Raw Blame History

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) * dprphysY = (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链接在浏览器内预览而非下载

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

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)

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/UPChrome_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均成功