自學Python之五 爬蟲基礎練習之SmartQQ協議

来源:http://www.cnblogs.com/jixin/archive/2016/01/15/5133629.html
-Advertisement-
Play Games

BAT站在中國互聯網的頂端,引導著中國互聯網的發展走向。。。既受到了多數程式員的關註,也在被我們所惦記著。。。 關於SmartQQ的協議來自HexBlog,根據他的博客我自己也一步一步的去分析,去嘗試,自己不瞭解不知道的總是神秘的,如果你有這種好奇心,那麼真相就只有一個。接下來我先把協議放出來...


  BAT站在中國互聯網的頂端,引導著中國互聯網的發展走向。。。既受到了多數程式員的關註,也在被我們所惦記著。。。

  關於SmartQQ的協議來自HexBlog,根據他的博客我自己也一步一步的去分析,去嘗試,自己不瞭解不知道的總是神秘的,如果你有這種好奇心,那麼真相就只有一個。接下來我先把協議放出來,至於分析方法,以後有機會再談談。。。其實我也是個半吊子水平。。。誰知道下次改了協議還靈不靈呢!

  登錄之前,獲取二維碼:https://ssl.ptlogin2.qq.com/ptqrshow?appid=501004106&e=0&l=M&s=5&d=72&v=4&t=0.22925435146316886,refer為:https://ui.ptlogin2.qq.com/cgi-bin/login

  迴圈獲取二維碼狀態(是否失效,是否在手機上授權):https://ssl.ptlogin2.qq.com/ptqrlogin?webqq_type=10&remember_uin=1&login2qq=1&aid=501004106&u1=http%3A%2F%2Fw.qq.com%2Fproxy.html%3Flogin2qq%3D1%26webqq_type%3D10&ptredirect=0&ptlang=2052&daid=164&from_ui=1&pttype=1&dumy=&fp=loginerroralert&action=0-0-136435&mibao_css=m_webqq&t=undefined&g=1&js_type=0&js_ver=10139&login_sig=&pt_randsalt=0   refer為:https://ui.ptlogin2.qq.com/cgi-bin/login

  獲取cookie中ptwebqq:這次的url是手機掃描二維碼之後得到的返回值。refer不變。

  獲取返回值vfwebqq:http://s.web2.qq.com/api/getvfwebqq?ptwebqq=" + ptwebqq + "&clientid=53999199&psessionid=&t=1446710396202。refer為http://s.web2.qq.com/proxy.html?v=20130916001&callback=1&id=1。

  成功登錄,得到uin,psessionid:http://d.web2.qq.com/channel/login2,refer為http://d.web2.qq.com/proxy.html?v=20130916001&callback=1&id=2,數據為:"r=%7B%22ptwebqq%22%3A%22"+ptwebqq+"%22%2C%22clientid%22%3A53999199%2C%22psessionid%22%3A%22%22%2C%22status%22%3A%22online%22%7D",host地址為:"d1.web2.qq.com"

  根據得到的信息獲取好友列表:http://s.web2.qq.com/api/get_user_friends2,數據為:data="r=%7B%22vfwebqq%22%3A%22"+vfwebqq+"%22%2C%22hash%22%3A%22"+__hash+"%22%7D",refer為:http://d.web2.qq.com/proxy.html?v=20130916001&callback=1&id=2

  讓我們來看看程式:

程式啟動,掃描二維碼登錄

  

  下麵我們用python來嘗試一下(分為兩個文件,其中繼續沿用我們的HttpClient類,以及WebQQ類,代碼如下):

 1 #HttpClient.py
  # -*- coding: utf-8 -*- 2 import cookielib, urllib, urllib2, socket 3 4 class HttpClient: 5 __cookie = cookielib.CookieJar() 6 __req = urllib2.build_opener(urllib2.HTTPCookieProcessor(__cookie)) 7 __req.addheaders = [ 8 ('Accept', 'application/javascript, */*;q=0.8'), 9 ('User-Agent', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)') 10 ] 11 urllib2.install_opener(__req) 12 13 def Get(self, url, refer=None): 14 try: 15 req = urllib2.Request(url) 16 if not (refer is None): 17 req.add_header('Referer', refer) 18 return urllib2.urlopen(req, timeout=120).read() 19 except urllib2.HTTPError, e: 20 return e.read() 21 except socket.timeout, e: 22 return '' 23 except socket.error, e: 24 return '' 25 26 def GetWithOutRead(self, url, refer=None): 27 try: 28 req = urllib2.Request(url) 29 if not (refer is None): 30 req.add_header('Referer', refer) 31 return urllib2.urlopen(req, timeout=120) 32 except urllib2.HTTPError, e: 33 return e.read() 34 except socket.timeout, e: 35 return '' 36 except socket.error, e: 37 return '' 38 39 def Post(self, url, data, refer=None): 40 try: 41 #req = urllib2.Request(url, urllib.urlencode(data)) 42 req = urllib2.Request(url,data) 43 if not (refer is None): 44 req.add_header('Referer', refer) 45 return urllib2.urlopen(req, timeout=120).read() 46 except urllib2.HTTPError, e: 47 return e.read() 48 except socket.timeout, e: 49 return '' 50 except socket.error, e: 51 return '' 52 53 def Download(self, url, file): 54 output = open(file, 'wb') 55 output.write(urllib2.urlopen(url).read()) 56 output.close() 57 61 def getCookie(self, key): 62 for c in self.__cookie: 63 if c.name == key: 64 return c.value 65 return '' 66 67 def setCookie(self, key, val, domain): 68 ck = cookielib.Cookie(version=0, name=key, value=val, port=None, port_specified=False, domain=domain, domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False) 69 self.__cookie.set_cookie(ck)
  1 #WebQQ.py
  2 # -*- coding: utf-8 -*-
  3 from Tkinter import *
  4 from time import sleep
  5 from HttpClient import HttpClient
  6 import json,io
  7 from multiprocessing import Process
  8 import multiprocessing
  9 from PIL import Image, ImageTk
 10 class WebQQ(HttpClient):
 11     def __init__(self):
 12         self.__cookie = ""
 13         self.__ptwebqq = ""
 14         self.__vfwebqq = ""
 15         self.__hash = ""
 16         self.__uin = ""
 17         self.__root = ""
 18         self.__psessionid = ""
 19         self.queue = multiprocessing.Queue()
 20 
 21     #獲取二維碼
 22     def __ptqrshow(self):
 23         img = self.Get(url="https://ssl.ptlogin2.qq.com/ptqrshow?appid=501004106&e=0&l=M&s=5&d=72&v=4&t=0.4139144900254905")
 24         if(img!=None):
 25             data_stream = io.BytesIO(img)
 26             imgfile = Image.open(data_stream)
 27             p = Process(target=self._run_proc, args=(imgfile,))
 28             p.start()
 29             print(u"二維碼下載完畢,請儘快掃描...")
 30             return True
 31         else:
 32             print(u"二維碼下載失敗")
 33             return False
 34 
 35     #檢測掃碼狀態,登錄進度
 36     def __ptqrlogin(self):
 37         res = self.Get("https://ssl.ptlogin2.qq.com/ptqrlogin?webqq_type=10&remember_uin=1"+
 38                        "&login2qq=1&aid=501004106&u1=http%3A%2F%2Fw.qq.com%2Fproxy.html%3Flogin2qq%3D1%26webqq_type%3D10"+
 39                        "&ptredirect=0&ptlang=2052&daid=164&from_ui=1&pttype=1&dumy=&fp=loginerroralert&action=0-0-136435"+
 40                        "&mibao_css=m_webqq&t=undefined&g=1&js_type=0&js_ver=10139&login_sig=&pt_randsalt=0",
 41                        "https://ui.ptlogin2.qq.com/cgi-bin/login")
 42         if(res!=None):
 43             result = res.find("登錄成功")
 44             if(result==-1):
 45                 sleep(1)
 46 
 47                 return self.__ptqrlogin()
 48             elif(result!=-1):
 49                 res = res.decode("UTF-8")
 50                 return self.__check_sig(res[res.find("http"):res.find(u"','0','登錄成功!'")].encode())
 51             else:
 52                 return False
 53         else:
 54             return False
 55     #獲得ptwebqq  cookie
 56     def __check_sig(self,url):
 57         res = self.Get(url=url,refer="https://ui.ptlogin2.qq.com/cgi-bin/login")
 58         if(res!=None):
 59             self.__ptwebqq = self.getCookie("ptwebqq")
 60             self.__getvfwebqq()
 61             return self.__login2()
 62         else:
 63             return False
 64     #獲得vfwebqq  cookie
 65     def __getvfwebqq(self):
 66         res = self.Get(url="http://s.web2.qq.com/api/getvfwebqq?ptwebqq="+self.__ptwebqq+
 67                        "&clientid=53999199&psessionid=&t=1446710396202",
 68                      refer="http://d.web2.qq.com/proxy.html?v=20130916001&callback=1&id=1")
 69         if(res!=None):
 70             jsn = json.loads(res)
 71             self.__vfwebqq = jsn["result"]["vfwebqq"]
 72     #登錄 獲取uin psessionid
 73     def __login2(self):
 74         data = "r=%7B%22ptwebqq%22%3A%22"+self.__ptwebqq+"%22%2C%22clientid%22%3A53999199%2C%22psessionid%22%3A%22%22%2C%22status%22%3A%22online%22%7D"
 75 
 76         res = self.Post(url = "http://d1.web2.qq.com/channel/login2",
 77                         data = data.encode(encoding="utf8"),
 78                         refer = "http://d.web2.qq.com/proxy.html?v=20130916001&callback=1&id=2")
 79         if(res==None):
 80             return False
 81         jsn = json.loads(res)
 82         if(jsn["retcode"]==0):
 83             self.__uin = jsn["result"]["uin"]
 84             self.__psessionid = jsn["result"]["psessionid"]
 85             self.__hash = self.__friendsHash(self.__uin,self.__ptwebqq)
 86             self.__get_user_friends()
 87             return True
 88         else:
 89             return False
 90     #好友的hash  參考HexBlog  
 91     def __friendsHash(self,uin,pt):
 92         N=[0 for x in range(4)]
 93         V=[0 for x in range(4)]
 94         U=[0 for x in range(8)]
 95         #    字元串轉換為字元數組
 96         k=pt.encode(encoding="UTF8")
 97         n=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"]
 98         for x in range(len(k)):
 99             N[x%4]^=ord(k[x])
100         x=int(uin)
101         V[0] = x >> 24 & 255 ^ 69;
102         V[1] = x >> 16 & 255 ^ 67;
103         V[2] = x >> 8 & 255 ^ 79;
104         V[3] = x & 255 ^ 75;        
105         for x in range(8):
106             U[x]=(x%2==0) and N[x>>1] or V[x>>1]
107         result=""
108         for x in U:
109             result+=n[x>>4&15]
110             result+=n[x&15]
111         return result
112     #獲取好友列表
113     def __get_user_friends(self):
114         data="r=%7B%22vfwebqq%22%3A%22"+self.__vfwebqq+"%22%2C%22hash%22%3A%22"+self.__hash+"%22%7D"
115         res=self.Post(url="http://s.web2.qq.com/api/get_user_friends2",
116                        data=data.encode(encoding="utf8"),
117                          refer="http://s.web2.qq.com/proxy.html?v=20130916001&callback=1&id=1")
118         if(res!=None):
119             #    記錄好友列表
120             jsn=json.loads(res)
121             if(jsn["retcode"]==0):
122                 #    正確返回列表後
123                 for x in jsn["result"]["marknames"]:
124                     print (x["markname"])
125     #心跳包並接收消息,現在不能用了
126     #def __poll(self):
127     #    data="r=%7B%22ptwebqq%22%3A%22"+self.__ptwebqq+"%22%2C%22clientid%22%3A53999199%2C%22psessionid%22%3A%22"+self.__psessionid +"%22%2C%22key%22%3A%22%22%7D"
128     #    res=self.Post(url="http://d1.web2.qq.com/channel/poll2",
129     #                  data=data.encode(encoding="utf8"),
130     #                  refer="http://d1.web2.qq.com/proxy.html?v=20151105001&callback=1&id=2")
131     #    if(res!=None):
132     #        print res
133 
134     def __check_queue(self):
135         try:
136             out = self.queue.get_nowait()
137             if out == 'stop':
138                 self.__do_stop()
139                 return
140             # Could check for other commands here, too
141         except :
142             pass
143         self.__root.after(100, self.__check_queue)
144 
145     def __stop(self):
146         self.queue.put('stop')
147 
148     def __do_stop(self):
149         self.__root.destroy()
150 
151     def _run_proc(self,imgfile):
152         self.__root = Tk()
153         result = ImageTk.PhotoImage(imgfile)
154         label = Label(self.__root, image=result)
155         label.pack()
156         self.__root.after(100, self.__check_queue)
157         self.__root.mainloop()
158     def run(self):
159         if(self.__ptqrshow()):
160             if(self.__ptqrlogin()):
161                 print(u"登錄成功")
162                 self.__stop()
163 
164 if  __name__ =="__main__":
165     qq=WebQQ()
166     qq.run()

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 常用方式: int a = 12; //註意:通常情況下,這個會設置成一個類變數,比如說Segement中的段鎖與copyOnWriteArrayList中的全局鎖 final ReentrantLock lock = new ReentrantLock()...
  • 最常用的方式: int a = 12; //註意:通常情況下,這個會設置成一個類變數,比如說Segement中的段鎖與copyOnWriteArrayList中的全局鎖 final ReentrantLock lock = new ReentrantLock...
  • 初次接觸python,寫的很簡單,開發工具PyCharm,python 3.4很方便python 部分模塊安裝時需要其他的附屬模塊之類的,可以先pip install wheel然後可以直接下載whl文件進行安裝pip installlxml-3.5.0-cp34-none-win32.whl定義一...
  • 在多線程應用中鎖是一個很簡單又很複雜的技術,之所以要用到鎖是因為在多進程/線程環境下,一段代碼可能會被同時訪問到,如果這段代碼涉及到了共用資源(數據)就需要保證數據的正確性。也就是所謂的線程安全。之前寫過一篇著於Java線程安全的博客:鏈接我是在寫一個服務端程式時應用到讀寫鎖,在一個記憶體緩存。先來看...
  • print ('hello world!')1. 下載python,並設置path系統環境變數;當在命令行中輸入python,出現如下界面,顯示安裝成功。2. 安裝最新的sublime,使用註冊機破解,或者Help->中輸入license,提供三個親測可用的激活碼,在文章最後。 打開sublime....
  • 原文網址:http://www.cnblogs.com/retop/p/4677148.html註:本人使用的Django1.8.3版本進行測試除了使用Django內置表單,有時往往我們需要自定義表單。對於自定義表單Post方式提交往往會帶來由CSRF(跨站請求偽造)產生的錯誤"CSRF verif...
  • 什麼是const限定符?Const限定符是我們通常所說的常量限定符,被const修飾的對象具有常量性質,只能讀,不能寫。為什麼使用const限定符?用const變數取代“魔數”,代碼更容易理解和維護。例如:以const常變數作為數組的界;const常變數作為switch的條件標號。C++“最小特權原...
  • 北京尚學堂提供1.Java集合框架是什麼?說出一些集合框架的優點?每種編程語言中都有集合,最初的Java版本包含幾種集合類:Vector、Stack、HashTable和Array。隨著集合的廣泛使用,Java1.2提出了囊括所有集合介面、實現和演算法的集合框架。在保證線程安全的情況下使用泛型和併發集...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...