|
Tło 0×00
Jak wyglądają czerwone koperty? Syn jego brata, Huer, powiedział: "Pieniądze są niemal porównywalne. Brat i córka Dao Yun powiedzieli: "Nie jest tak dobre jak u mojej ciotki przez wiatr." "Wszyscy rozumieją tło, to Nowy Rok i dzień, gdy czerwone koperty latają po całym niebie. Tak się złożyło, że dwa dni temu nauczyłem się Pythona i byłem bardziej podekscytowany, więc studiowałem i analizowałem pełzanie czerwonych kopert Weibo, dlaczego czerwone koperty Weibo zamiast Alipay czerwone, bo rozumiem tylko Internet, a jeśli będę miał na to siłę, być może w przyszłości zgłębię algorytm whack-a-mole. Ponieważ jestem początkujący w Pythonie, ten program jest też trzecim, który napisałem po nauce Pythona, więc proszę, nie pytaj osobiście, jeśli w kodzie jest jakaś przeszkoda, skupiam się na idei, a jeśli jest jakaś przeszkoda w pomyśle, proszę, nie poruszaj tego osobiście, widzisz, IE ma twarz, by ustawić się jako domyślna przeglądarka, piszę artykuł o podejrzaniu też jest akceptowalne...... Używam Pythona 2.7 i mówi się, że jest duża różnica między Pythonem 2 a Pythonem 3.
0×01 Pomysły Byłem zbyt leniwy, by opisać to słowami, więc narysowałem szkic i wszyscy powinni to zrozumieć.
Przede wszystkim stara zasada: najpierw wprowadź bibliotekę, której nie wiesz, czy jest przydatna, ale bez której nie możesz się obejść: [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] Następnie zadeklaruj inne zmienne, które będziesz musiał wykorzystać później:
[mw_shl_code=java,true]reload(sys)sys.setdefaultencoding('utf-8&') #将字符编码置为utf-8luckyList=[] #红包列表lowest=10 #能忍受红包领奖记录最低为多少[/mw_shl_code]Tutaj używana jest biblioteka rsa, która domyślnie nie jest dołączona do Pythona. Muszę go zainstalować :https://pypi.python.org/pypi/rsa/
Po pobraniu uruchom setpy.py instalację, a potem możemy rozpocząć etapy rozwoju.
0×02 Login Weibo Działanie polegające na chwytaniu czerwonych kopert musi być wykonane po zalogowaniu, więc musi istnieć funkcja logowania, logowanie nie jest kluczem, kluczem jest zachowanie ciasteczek, tutaj wymagana jest współpraca cookielib. [mw_shl_code=Java,true]cj = cookielib. CookieJar()opener = urllib2.build_opener(urllib2. HTTPCookieProcessor(cj))urllib2.install_opener(opener)[/mw_shl_code] W ten sposób wszystkie operacje sieciowe z użyciem openera obsługują stan ciasteczek, choć niewiele o tym wiem, ale to niesamowite uczucie. Następnie musimy zapakować dwa moduły: jeden to moduł akwizycji danych, który służy po prostu do pobierania danych, a drugi do POST-owania. [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') zwróć tekst z wyjątkiem wyjątku, 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() zwróć tekst z wyjątkiem Wyjątku, e: print u'Request exception, url: '+url[/mw_shl_code] Dzięki tym dwóm modułom możemy GET i POST danych, z których powodem, dla którego getData dekoduje, a potem koduje, jest to, że w Win7 zawsze zniekształcałem wynik podczas debugowania, więc dodałem trochę przetwarzania kodowania, ale to nie jest sedno – funkcja logowania poniżej to rdzeń logowania na 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) serwertime = 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) key = rsa. PublicKey(rsaPublickey,65537) message = str(servertime) +'\t' + str(nonce) + '\n' + str(pwd) sp = binascii.b2a_hex(rsa.encrypt(message,key)) nagłówek = {'User-Agent' : 'Mozilla/5.0 (kompatybilne; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)'} param = { 'entry': 'weibo', 'gateway': '1', 'from': ''', 'savestate': '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"--------- Logowanie zakończyło się! ------- "drukuj" ----------......---------- "poza wyjątkiem, e: wydrukuj u" --------- logowanie się nie powiodło! -------" drukuj "----------......----------" exit(0)[/mw_shl_code] Parametry i algorytmy szyfrowania są skopiowane z Internetu, nie rozumiem tego zbyt dobrze, prawdopodobnie najpierw chodzi o żądanie znacznika czasu i klucza publicznego, potem szyfrowanie RSA, a na końcu przetwarzanie i przesłanie do interfejsu logowania Siny, po pomyślnym zalogowaniu z Sina zwróci się adres Weibo, musisz o niego poprosić, aby status logowania mógł zadziałać w pełni. Po pomyślnym zalogowaniu kolejne żądania będą zawierać ciasteczko aktualnego użytkownika.
0×03 Oznaczony rysunek na czerwonej kopercie Po pomyślnym zalogowaniu się na Weibo nie mogę się doczekać, aż najpierw znajdę czerwoną kopertę, żeby spróbować najpierw w przeglądarce. W końcu znalazłem stronę z czerwonym przyciskiem koperty, F12 przywołał debugger, żeby zobaczyć, czego żąda pakiet danych.
Widać, że adres żądania to http://huodong.weibo.com/aj_hongbao/getlucky, są dwa główne parametry: jeden to ouid, czyli czerwony identyfikator koperty, widoczny w URL, drugi parametr share decyduje, czy udostępnić go do Weibo, i jest _t, do którego nie wiem, do czego służy. Teoretycznie możesz zakończyć ekstrakcję czerwonych kopert, wysyłając trzy parametry do tego URL, ale gdy faktycznie je przesłasz, serwer magicznie zwróci ci taki ciąg znaków: [mw_shl_code=java, prawda] {"code":303403,"msg":"Przepraszam, nie masz uprawnień do dostępu do tej strony","data":[]}[/mw_shl_code] Nie panikuj w tym momencie, według mojego wieloletniego doświadczenia w tworzeniu stron internetowych, programista drugiej strony powinien prosto ocenić referer, bardzo prosto, skopiować wszystkie nagłówki poprzedniego żądania. [mw_shl_code=java,true]def getLucky(id): #抽奖程序 print u"--- narysuj czerwoną kopertę z:"+str(id)+"---" print "----------......----------" if checkValue(id)==False: #不符合条件, to funkcja return później luckyUrl="http://huodong.weibo.com/aj_hongbao/getlucky" param={ 'ouid':id, 'share':0, '_t':0 } nagłówek= { '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, podobnie jak Gecko) Chrome/33.0.1750.146 BIDUBrowser/6.x Safari/537.36', 'X-Requested-With':'XMLHttpRequest' } res = postData(luckyUrl,param, nagłówek)[/mw_shl_code] W tym przypadku teoretycznie nie ma problemu, ale w rzeczywistości go nie ma. Po zakończeniu akcji loterii musimy ocenić status, a zwrócona RES to ciąg json, gdzie kod to 100000 jest pomyślny, a jeśli jest to 90114, to jest to górna granica dzisiejszej loterii, a pozostałe wartości również są niezaliczone, więc: [mw_shl_code=java,true]hbRes=json.loads(res)if hbRes["code"]=='901114': #今天红包已经抢完 print u"--------- osiągnął górną granicę---------" print "----------......----------" log("lucky', str(id)+'---'+str(hbRes["code"])+'---'+hbRes["data"]["title"]) exit(0)elif hbRes["code"]=='100000':#成功 print u"---------Życząc Ci powodzenia---------" print "----------......----------" log('success',str(id)+'---'+res) exit(0) if hbRes["data"] oraz 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], gdzie log jest także funkcją, którą dostosowuję, a która służy do zapisywania logów: [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]
|