Files

53 lines
3.7 KiB
Python
Raw Permalink Normal View History

2026-09-03 15:35:23 +08:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""聚焦探测“生成过程”:招聘报表页点下载图标 -> 看参数窗内容 -> 确定 -> 观察 toast/任务中心出现与完成。"""
import json, urllib.request, time
D = "http://127.0.0.1:10086/command"; S = "2haohr"
def call(a, args, t=90):
b = json.dumps({"action": a, "args": args, "session": S}).encode()
r = urllib.request.Request(D, data=b, headers={"Content-Type": "application/json"})
return json.loads(urllib.request.urlopen(r, timeout=t).read().decode())
def ev(c):
try: return call("evaluate", {"code": c}).get("data", {}).get("value")
except Exception as e: return "EXC:" + str(e)[:80]
HOOK = r"""(()=>{window.__cap=window.__cap||[];if(!HTMLAnchorElement.prototype.__hk){const ac=HTMLAnchorElement.prototype.click;
HTMLAnchorElement.prototype.click=function(){try{const h=this.href||'';if(h&&/-cdn\.2haohr|attname=|\.xlsx|\.xls|\.docx/i.test(h))window.__cap.push(h);}catch(e){}return ac.apply(this,arguments);};HTMLAnchorElement.prototype.__hk=1;}return 'ok';})()"""
CLICK_ICON = r"""(()=>{const us=[...document.querySelectorAll('use')].filter(u=>(u.getAttribute('xlink:href')||u.getAttribute('href'))==='#icon-download');
for(const u of us){const b=u.closest('button,a,[role=button]');if(b){b.click();return 'ok';}}return 'none';})()"""
# 参数窗全文 + 按钮列表
MODAL = r"""(()=>{const ms=[...document.querySelectorAll('[class*=modal],[class*=Modal],[role=dialog],[class*=dialog],[class*=drawer],[class*=Drawer]')];
const vis=ms.filter(m=>{const r=m.getBoundingClientRect();return r.width>200&&r.height>80&&getComputedStyle(m).display!=='none';});
if(!vis.length)return 'NO_MODAL';const m=vis[vis.length-1];
const btns=[...m.querySelectorAll('button,a')].map(b=>(b.innerText||'').trim()).filter(t=>t&&t.length<10);
return JSON.stringify({text:(m.innerText||'').replace(/\n{2,}/g,'\n').slice(0,400),btns:[...new Set(btns)]});})()"""
CONFIRM = r"""(()=>{const ms=[...document.querySelectorAll('[class*=modal],[class*=Modal],[role=dialog],[class*=dialog],[class*=drawer],[class*=Drawer]')];
const vis=ms.filter(m=>{const r=m.getBoundingClientRect();return r.width>200&&r.height>80&&getComputedStyle(m).display!=='none';});
if(!vis.length)return 'NO_MODAL';const m=vis[vis.length-1];
for(const t of ['确定','确认','下载','导出','生成']){const b=[...m.querySelectorAll('button,a')].find(x=>(x.innerText||'').trim()===t&&x.getBoundingClientRect().width>0);if(b){b.click();return 'click:'+t;}}return 'noconfirm';})()"""
TOAST = r"""(()=>{const a=[];document.querySelectorAll('[class*=message],[class*=Message],[class*=toast],[class*=notify],[class*=Notification]').forEach(el=>{const t=(el.innerText||'').trim();if(t&&t.length<60&&el.getBoundingClientRect().width>0)a.push(t);});return JSON.stringify([...new Set(a)]);})()"""
TC = r"""(()=>{const tc=document.querySelector('[class*=taskCenter]');if(!tc)return 'NO_TC';
const dls=[...tc.querySelectorAll('a')].filter(a=>(a.innerText||'').trim()==='下载');
return JSON.stringify({dl:dls.length,text:(tc.innerText||'').replace(/\n{2,}/g,'\n').slice(0,300)});})()"""
def main():
call("find_tab", {"url": "2haohr.com"})
call("navigate", {"url": "https://2haohr.com/recruit/statistics/recruit-report", "newTab": False})
time.sleep(7)
ev(HOOK)
print("icon click:", ev(CLICK_ICON))
time.sleep(2)
print("MODAL:", ev(MODAL))
print("confirm:", ev(CONFIRM))
# 观察生成过程
for i in range(10):
time.sleep(3)
cap = ev("(window.__cap&&window.__cap.length)||0")
print(" t+%ds cap=%s toast=%s" % (3*(i+1), cap, ev(TOAST)))
if isinstance(cap, int) and cap > 0:
print(" >>> 捕获直链!"); break
print("TASK_CENTER:", ev(TC))
if __name__ == "__main__":
main()