文件
phonerail/BOM/_src/scrape.py

30 行
2.0 KiB
Python

import asyncio,json,urllib.parse,random,os,time
import cdp
EX=r'''JSON.stringify([...document.querySelectorAll("a")].filter(a=>/item\.taobao\.com\/item|detail\.tmall\.com\/item/.test(a.href)&&/¥/.test(a.innerText)).slice(0,24).map(a=>{const id=(a.href.match(/[?&]id=(\d+)/)||[])[1];const t=a.innerText.split("\n").map(s=>s.trim()).filter(Boolean);const i=t.indexOf("¥");let p="";if(i>=0){p=t[i+1]||"";if(t[i+2]&&/^\.\d+$/.test(t[i+2]))p+=t[i+2];}const sales=t.find(s=>/人付款|人收货|已售/.test(s))||"";return {id,tmall:/tmall/.test(a.href),title:t[0],price:p,sales,shop:t[t.length-1],tags:t.slice(1,i).join("/")};}))'''
async def main():
Q=json.load(open('queries.json',encoding='utf-8'))
out=json.load(open('tb.json',encoding='utf-8')) if os.path.exists('tb.json') else {}
ws=await cdp.open_ws()
for n,x in enumerate(Q):
if x['sid'] in out and out[x['sid']]['items']: continue
await cdp.send(ws,'Page.navigate',{'url':'https://s.taobao.com/search?q='+urllib.parse.quote(x['q'])})
items=[]
for k in range(40):
await asyncio.sleep(1)
v=await cdp.ev(ws,EX)
items=json.loads(v) if v else []
if len(items)>=8 or (items and k>10): break
if k==20 and not items:
txt=await cdp.ev(ws,'document.body.innerText.slice(0,300)+location.href')
print('NO ITEMS/CAPTCHA?',x['q'],(txt or '')[:200].replace('\n',' '),flush=True)
for w in range(100):
await asyncio.sleep(3); v=await cdp.ev(ws,EX); items=json.loads(v) if v else []
if items: break
if w==30: await cdp.send(ws,'Page.navigate',{'url':'https://s.taobao.com/search?q='+urllib.parse.quote(x['q'])})
break
out[x['sid']]={'q':x['q'],'items':items,'ts':time.time()}
json.dump(out,open('tb.json','w',encoding='utf-8'),ensure_ascii=False,indent=1)
print(n,x['sid'],x['q'],len(items),items[0]['price'] if items else '',flush=True)
await asyncio.sleep(30)
asyncio.run(main())