first commit
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user