Files

71 lines
3.4 KiB
Python
Raw Permalink Normal View History

2026-09-03 15:35:23 +08:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""探测任务中心(taskCenter):结构、任务项状态、下载链路。并测试整表页的导出图标(hover tooltip)。"""
import json, urllib.request, base64, time, os
D = "http://127.0.0.1:10086/command"; S = "2haohr"
def call(a, args, timeout=120):
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=timeout).read().decode())
def ev(code, timeout=120):
try:
return call("evaluate", {"code": code}, timeout).get("data", {}).get("value")
except Exception as e:
return "EXC:" + str(e)[:80]
HOOK = r"""(()=>{window.__cap=[];const ac=HTMLAnchorElement.prototype.click;
HTMLAnchorElement.prototype.click=function(){try{const h=this.href||'';if(h&&/prv-cdn|attname=|\.xlsx|\.xls|\.docx|\.doc|\.zip/i.test(h))window.__cap.push(h);}catch(e){}return ac.apply(this,arguments);};return 'ok';})()"""
# 读取任务中心:定位 taskCenter 容器,列出每个任务项(名称/状态/是否有下载)
TASKS = r"""(()=>{
const tc=document.querySelector('[class*=taskCenter]');
if(!tc)return 'NO_TASKCENTER';
const items=[];
// 任务项通常是含 info_ 名称 + right_ 状态 的行
tc.querySelectorAll('[class*=info_]').forEach(info=>{
const row=info.closest('[class*=item],li,tr')||info.parentElement;
const name=(info.innerText||'').replace(/\n+/g,' ').trim().slice(0,40);
let dl='';const a=row&&row.querySelector('a');
const stat=row?(row.innerText||'').replace(/\n+/g,'|').slice(0,40):'';
items.push({name:name,row:stat});
});
return JSON.stringify({open:getComputedStyle(tc).display,cnt:items.length,items:items.slice(0,10)});
})()"""
# 点击任务中心里第 idx 个“下载”链接
CLICK_TASK_DL = r"""(function(idx){
const tc=document.querySelector('[class*=taskCenter]');if(!tc)return 'NO_TC';
const dls=[...tc.querySelectorAll('a')].filter(a=>(a.innerText||'').trim()==='下载');
if(idx>=dls.length)return 'IDX_OOB len='+dls.length;
dls[idx].click();return 'clicked '+idx+'/'+dls.length;
})(%d)"""
FETCH_LAST = r"""(()=>{try{if(!window.__cap.length)return 'NO_HREF';
const u=window.__cap[window.__cap.length-1];const x=new XMLHttpRequest();x.open('GET',u,false);
x.overrideMimeType('text/plain;charset=x-user-defined');x.send();if(x.status!==200)return 'HTTP'+x.status;
const s=x.responseText;let out='';const CH=8192;for(let i=0;i<s.length;i+=CH){let c='';const e=Math.min(i+CH,s.length);for(let j=i;j<e;j++)c+=String.fromCharCode(s.charCodeAt(j)&0xff);out+=c;}
window.__b64=btoa(out);const m=u.match(/attname=([^&]+)/);let name=m?decodeURIComponent(m[1]):('f_'+Date.now());
return JSON.stringify({size:s.length,name:name});}catch(e){return 'EX '+e.message;}})()"""
def main():
call("find_tab", {"url": "2haohr.com"})
print("== 当前任务中心 ==")
print(ev(TASKS))
ev(HOOK)
# 实测抓第一个任务下载
print("click:", ev(CLICK_TASK_DL % 0))
time.sleep(2.5)
meta = ev(FETCH_LAST)
print("fetch:", meta)
if isinstance(meta, str) and meta.startswith("{"):
info = json.loads(meta); data = base64.b64decode(ev("window.__b64||''"))
os.makedirs("downloads/_test", exist_ok=True)
out = "downloads/_test/task_" + info["name"]
open(out, "wb").write(data); print("落盘:", out, len(data))
if __name__ == "__main__":
main()