53 lines
3.7 KiB
Python
53 lines
3.7 KiB
Python
#!/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()
|