|
0×00 Contesto
Com'è le buste rosse? Il figlio di suo fratello, Huer, disse: "I soldi sono quasi paragonabili. Il fratello e la figlia Dao Yun dissero: "Non è buono come mio zio a causa del vento." "Tutti capiscono il contesto, è Capodanno, ed è il giorno in cui buste rosse volano ovunque nel cielo. È successo che ho imparato Python due giorni fa, e mi sono entusiasmato di più, così ho studiato e studiato il crawling delle buste rosse di Weibo, perché le buste rosse di Weibo invece di quelle di Alipay, perché capisco solo il Web, e se avrò l'energia, potrei anche studiare l'algoritmo whack-a-mole in futuro. Poiché sono un principiante in Python, questo programma è anche il terzo che ho scritto dopo aver imparato Python, quindi per favore non insistere di persona se c'è qualche buco nel codice, l'attenzione è sull'idea, beh, se c'è qualche buco nell'idea, per favore non toccarlo di persona, vedi, IE ha il volto di impostarsi come browser predefinito, scrivere un articolo scadente è accettabile...... Uso Python 2.7, e si dice che ci sia una grande differenza tra Python 2 e Python 3.
0×01 Idee Ero troppo pigro per descriverlo a parole, così ho fatto uno schizzo, e tutti dovrebbero riuscire a capirlo.
Prima di tutto, la vecchia regola: introdurre prima una libreria per cui non sai se è utile ma che non puoi fare a meno: [mw_shl_code=java,true]import re import urllib import urllib2 import cookielib import base64 import binascii import os import json import sys import cPickle as p import rsa[/mw_shl_code] Poi dichiara altre variabili che dovrai usare in seguito:
[mw_shl_code=java,true]reload(sys)sys.setdefaultencoding('utf-8&') #将字符编码置为utf-8luckyList=[] #红包列表lowest=10 #能忍受红包领奖记录最低为多少[/mw_shl_code]Qui viene utilizzata una libreria rsa, che di default non è inclusa in Python. Devo installarlo :https://pypi.python.org/pypi/rsa/
Dopo averlo scaricato, esegui setpy.py installazione e poi possiamo iniziare i passaggi di sviluppo.
0×02 Accesso Weibo L'azione di prendere le buste rosse deve essere eseguita dopo l'accesso, quindi deve esserci una funzione di login, il login non è la chiave, la chiave è la conservazione dei cookie, qui è richiesta la collaborazione di cookielib. [mw_shl_code=java,true]cj = cookielib. CookieJar()opener = urllib2.build_opener(urllib2. HTTPCookieProcessor(cj))urllib2.install_opener(opener)[/mw_shl_code] In questo modo, tutte le operazioni di rete che usano l'opener gestiranno lo stato dei cookie, anche se non ne so molto, ma è una sensazione fantastica. Successivamente, dobbiamo incapsulare due moduli, uno è il modulo acquisizione dati, che viene usato semplicemente per ottenere dati, e l'altro per POST dati. [mw_shl_code=java,true]def getData(url) : try: req = urllib2. Request(url) result = opener.open(req) text = result.read() text=text.decode("utf-8").encode("gbk",'ignore') restituisci testo tranne Exception, e: print u' request exception, url: '+url print e def postData(url,data,header) : try: data = urllib.urlencode(data) req = urllib2. Request(url,data,header) result = opener.open(req) text = result.read() return text excepto Exception, e: print u'Request exception, url: '+url[/mw_shl_code] Con questi due moduli possiamo GET e POST dati, tra cui il motivo per cui getData decode e poi encode è che sotto Win7 ho sempre distorto l'output durante il debug, quindi ho aggiunto un po' di elaborazione della codifica, ma non è questo il punto, la funzione di login qui sotto è il nucleo dell'accesso Weibo. [mw_shl_code=java,true]def login(nick, pwd): print u"----------login----------" print "----------......----------" prelogin_url= 'http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=%s&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.15)&_= 1400822309846' % nick preLogin = getData(prelogin_url) servertime = re.findall('"servertime":(.+?),' , preLogin)[0] pubkey = re.findall('"pubkey":"(.+?)",' , preLogin)[0] rsakv = re.findall('"rsakv":"(.+?)",' , preLogin)[0] nonce = re.findall('"nonce":"(.+?)",' , preLogin)[0] #print bytearray('xxxx','utf-8') su = base64.b64encode(urllib.quote(nick)) rsaPublickey= int(pubkey,16) chiave = rsa. PublicKey(rsaPublickey,65537) messaggio = str(servertime) +'\t' + str(nonce) + '\n' + str(pwd) sp = binascii.b2a_hex(rsa.encrypt(message,key)) header = {'User-Agent' : 'Mozilla/5.0 (compatibile; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)'} param = { 'entry': 'weibo', 'gateway': '1', 'from': '', 'salvestate': '7', 'userticket': '1', 'ssosimplelogin': '1', 'vsnf': '1', 'vsnval': '', 'su': su, 'service': 'miniblog', 'servertime': servertime, 'nonce': nonce, 'pwencode': 'rsa2', 'sp': sp, 'encoding': 'UTF-8', 'url': 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack', 'returntype': 'META', 'rsakv' : rsakv, } s = postData('http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)',param,header) try: urll = re.findall("locatio remove n.replace\(\'(.+?) \'\); " , s)[0] login=getData(urll) print u"--------- Accesso riuscito! ------- "stampa" ----------......---------- "eccezione eccezionale, e: print u" --------- accesso fallito! -------" stampa "----------......----------" exit(0)[/mw_shl_code]I parametri e gli algoritmi di crittografia sono copiati da Internet, non capisco molto bene, probabilmente bisogna richiedere prima un timestamp e una chiave pubblica, poi la crittografia RSA e infine elaborare l'elaborazione e inviarla all'interfaccia di login Sina, dopo aver effettuato il login con successo da Sina, restituirà un indirizzo Weibo, devi richiederlo affinché lo stato di accesso possa avere effetto completo, Dopo un accesso riuscito, le richieste successive porteranno il cookie dell'utente attuale.
0×03 Disegno designato della busta rossa Dopo aver effettuato il login con successo su Weibo, non vedo l'ora di trovare una busta rossa per provare prima, ovviamente, prima nel browser. Finalmente ho trovato una pagina con un pulsante rosso per la busta, F12 ha evocato il debugger per vedere cosa stava richiedendo il pacchetto dati.
Puoi vedere che l'indirizzo della richiesta è http://huodong.weibo.com/aj_hongbao/getlucky, ci sono due parametri principali: uno è ouid, cioè l'id rosso della busta che si vede nell'URL, l'altro parametro di condivisione determina se condividerlo con Weibo, e c'è un _t non so a cosa serva. Ok, ora teoricamente puoi completare l'estrazione delle buste rosse inviando tre parametri a questo URL, ma quando effettivamente invii i parametri, scoprirai che il server ti restituirà magicamente una stringa di questo tipo: [mw_shl_code=java,vero] {"code":303403,"msg":"Mi dispiace, non hai il permesso di accedere a questa pagina","data":[]}[/mw_shl_code] Non farti prendere dal panico in questo momento, secondo i miei molti anni di esperienza nello sviluppo web, il programmatore dell'altra parte dovrebbe giudicare chi fa referenza, molto semplice, copia tutte le intestazioni della richiesta precedente. [mw_shl_code=java,true]def getLucky(id): #抽奖程序 print u"--- disegna invilupupo rosso da:"+str(id)+"---" stampa "----------......----------" if checkValue(id)==False: #不符合条件, questa è la funzione return più tardi luckyUrl="http://huodong.weibo.com/aj_hongbao/getlucky" param={ 'ouid':id, 'share':0, '_t':0 } header= { 'Cache-Control':'no-cache', 'Content-Type':'application/x-www-form-urlencoded', 'Origin':'http://huodong.weibo.com', 'Pragma':'no-cache', 'Referer': 'http://huodong.weibo.com/hongbao/'+str(id), 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, come Gecko) Chrome/33.0.1750.146 BIDUBrowser/6.x Safari/537.36', 'X-Requested-With':'XMLHttpRequest' } res = postData(luckyUrl,param, header)[/mw_shl_code] In questo caso, in teoria non c'è problema, ma in realtà non c'è problema. Dopo che l'azione della lotteria è completata, dobbiamo giudicare lo stato, e la re restituita è una stringa json, dove il codice è 100000 è successo, e se è 90114, è il limite superiore della lotteria odierna, e anche gli altri valori vengono falliti, quindi: [mw_shl_code=java,true]hbRes=json.loads(res)if hbRes["code"]=='901114': #今天红包已经抢完 print u"--------- ha raggiunto il limite superiore---------" print "----------......----------" log('lucky', str(id)+'---'+str(hbRes["code"])+'---'+hbRes["data"]["title"]) exit(0)elif hbRes["code"]=='100000':#成功 print u"---------Ti auguro prosperità---------" print "----------......----------" log('success',str(id)+'---'+res) exit(0) se hbRes["data"] e hbRes["data"]["title"]: print hbRes["data"]["title"] print "----------......----------" log('lucky', str(id)+'---'+str(hbRes["code"])+'---'+hbRes["data"]["title"])else: print u"---------Request error---------" print "----------......----------" log('lucky', str(id)+'---'+res)[/mw_shl_code], dove log è anche una funzione che personalizzo, usata per registrare i log: [mw_shl_code=java,true]def log(type,text): fp = open(type+'.txt','a') fp.write(text) fp.write('\r\n') fp.close()[/mw_shl_code]
|