# 引子
最近偶爾在極客學院看一會教程視頻,主要是擴展視野, 感覺有的視頻教程的質量還是不錯的,至少能夠把人帶入門。
然而,高質量視頻要盈利,學院針對*非年度會員*僅提供第一章節的試看,就是想誘惑你,注冊,消費。
近期學院有活動,VIP試用可以通過邀請方式來續期,會員A邀請好友B,B通過鏈接注冊成功后,A和B都同時會增加一個月的會員。
就是這里,會員不是關鍵,關鍵是有相對長一點的時間,可以收集各類教程視頻,是不是可以整一個這樣的程序:
> 自動登陸學院,爬取分類教程頁面,對頁面分析出視頻地址,然后分別存儲視頻到本地?
# 初步分析
## 登錄認證
學院的登錄認證支持兩種,一種使用通過手機注冊驗證成為學院會員;另一種第三方認證(支持QQ,微博等),通過第三方認證登錄后,自動成為會員。
在這里,暫時實現使用第三方認證登錄方式,后面如有需要再考慮使用學院賬號登錄。
## 頁面分析
通過F12,看到學院播放視頻使用了`video-js`控件,如果在支持HTML5的瀏覽器中,在video塊中是可以看到視頻源`source`的地址,這個后面再細作分析。
# 詳細過程
##? 獲得認證碼
抓包分析過程,用到了fiddler和瀏覽器的開發者工具,用于分析使用瀏覽器登錄過程都做了什么操作
模擬網頁請求主要使用`python`,引用庫: requests, base64, hashlib, rsa等
### 從'QQ登錄'開始
點擊‘QQ登錄’按鈕后,抓包分析請求和回應:
```
<---請求
GET /connect/qq HTTP/1.1\r\n
Host: passport.jikexueyuan.com\r\n
Referer: http://www.jikexueyuan.com/\r\n
--->回應
HTTP/1.1 302 Moved Temporarily\r\n
Location: https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101119675&redirect_uri=http://passport.jikexueyuan.com/connect/success?t=qq&state=19325e260ec40f525abcfa2545b0c9a4&scope=get_user_info\r\n
```
這里有一個HTTP 302跳轉至`https://graph.qq.com/oauth2.0/authorize`,用于獲取'Authorization Code'(請參考`http://open.qq.com/`說明)
騰訊的認證使用了OAUTH 2.0的server-side模式,獲取認證碼的接口定義如下:
>response_type? 必須? 授權類型,此值固定為“code”。
>client_id? 必須? 申請QQ登錄成功后,分配給應用的appid。
>redirect_uri? 必須? 成功授權后的回調地址,必須是注冊appid時填寫的主域名下的地址,建議設置為網站首頁或網站的用戶中心。注意需要將url進行URLEncode。
>state? 必須? client端的狀態值。用于第三方應用防止CSRF攻擊,成功授權后回調時會原樣帶回。請務必嚴格按照流程檢查用戶與state參數狀態的綁定。
fiddler抓日志看的話,可以看到,就是學院的通行證使用QQ登錄模塊,向騰訊請求認證,主要包含cliet_id和state,redirect_uri為本網站。
然后我們接著看,還可以看到,騰訊graph.qq.com/oauth2.0/authorize模塊會會引導至此頁面http://openapi.qzone.qq.com:
```
<---
GET /oauth/show?which=ConfirmPage&display=pc&response_type=code&client_id=101119675&redirect_uri=http://passport.jikexueyuan.com/connect/success?t=qq&state=19325e260ec40f525abcfa2545b0c9a4&scope=get_user_info HTTP/1.1\r\n
Host: openapi.qzone.qq.com\r\n
Referer: http://www.jikexueyuan.com/\r\n
--->
HTTP/1.1 200 OK\r\n
```
?? 如果是瀏覽器,會繼續請求下載登錄模塊,騰訊這里使用IFrame顯示:
? ```
<---
GET /cgi-bin/xlogin/appid=716027609&style=23&login_text=授權并登錄&hide_title_bar=1&hide_border=1&target=self&s_url=http://openapi.qzone.qq.com/oauth/login_jump&pt_3rd_aid=101119675&pt_feedback_link=http://support.qq.com/write.shtml?fid=780&SSTAG=www.jikexueyuan.com.appid101119675 HTTP/1.1\r\n
Host: xui.ptlogin2.qq.com\r\n
Referer: http://www.jikexueyuan.com/\r\n
--->
HTTP/1.1 200 OK\r\n
```
??? 這里就出現了登錄按鈕,當然也有掃碼登錄,這里我只分析了無驗證登錄。我們繼續分析,輸入QQ賬號和密碼然后點擊“授權并登錄”。
??? 瀏覽器會自動登陸,并且導向到學院主頁,我們看一下fiddler都抓到了什么:
?? 1. 校驗,返回是否有效登錄,并且返回是否需要驗證碼
???2. 登錄,這里就是關鍵的提交登錄代碼
?? 3. 登錄跳轉
?? 4. 上報,一個是mstats_report,一個是report_vm
? ?5. 最后是請求授權碼,如果有返回值,無論成功與否,騰訊鑒權平臺根據redirect_url自動跳轉
?? 這個步驟有點多,但是3,4步是否必要需要驗證(我是實現了)。還是繼續分析HTTP交互過程。
? 1. 請求校驗,返回是否有效登錄,并且返回是否需要驗證碼:
```
<---請求
method: GET
host: check.ptlogin2.qq.com
Param:
GET /check?regmaster=&pt_tea=1&pt_vcode=1&uin=909066038&appid=716027609&js_ver=10138&js_type=1&login_sig=6*d0PfHlaCk9wcqRt1diUu94fNStHN*zaUujdam*-Y9bAegZRbdjYmphbCgVn*B8&u1=http://openapi.qzone.qq.com/oauth/login_jump
--->回應
JSON:
ptui_checkVC('0','!OVV','\x00\x00\x00\x00\x36\x2f\x3f\x36','95acfe9e4e59152feb350ef9065c844acb6881fc7c4915fc96ce9bc91a05b75b0e1b66838644b89cfdf95f4e17b1f657fd43b304d390b2b4','0');
```
這個處理過程請求的參數中,login_sig是從cookies取得,其他參數沒有特殊的,返回值第一個標識是否需要校驗碼,'0'標識不需要,第二個為校驗碼,登錄時需要使用。第三個為轉換后的賬號,第四個為pt_verifysession_v1可以從cookies中取得,登錄時使用。
? 2. 登錄,這里就是關鍵的提交登錄代碼
```
<---請求
GET /login?u=909066038&verifycode=!OVV&pt_vcode_v1=0&pt_verifysession_v1=95acfe9e4e59152feb350ef9065c844acb6881fc7c4915fc96ce9bc91a05b75b0e1b66838644b89cfdf95f4e17b1f657fd43b304d390b2b4&p=YNMEEekeNoSmg9XjMRICahp6OF8iPOYcfytn7Yu
host: ptlogin2.qq.com
--->回應
JSON:
ptuiCB('0','0','http://openapi.qzone.qq.com/oauth/login_jump','0','\347\231\273\345\275\225\346\210\220\345\212\237\357\274\201', 'Yo\/jyyo');
```
? 登錄這里有個參數需要注意,就是密碼,p為加密后的密碼,騰訊的加密方法可以參考c_login_2.js實現。
? 3.登錄跳轉,請求了http://openapi.qzone.qq.com/oauth/login_jump,不用分析
? 4.上報,一個是mstats_report,一個是report_vm, 不用分析
? 5. 最后是請求授權碼,如果有返回值,無論成功與否,騰訊鑒權平臺根據redirect_url自動跳轉
```
<---請求
Post: 注意是post
host: https://graph.qq.com/oauth2.0/authorize
--->回應
??參考下表
```
?? 至此,以我跳躍的思路,描述完從登錄到獲取鑒權碼的過程,下一篇進行編碼。