微博爬蟲“免登入”技巧詳解及Java 實現- 程式人生

文章推薦指數: 80 %
投票人數:10人

作為前篇的重點內容,本文詳細介紹如何獲取相關的Cookie並重新封裝Httpclient達到免登入的目的,以支援微博上的各項資料抓取任務。

下面就從微博 ... 程式人生>>微博爬蟲“免登入”技巧詳解及Java實現 微博爬蟲“免登入”技巧詳解及Java實現 阿新••發佈:2018-12-23 一、微博一定要登入才能抓取? 目前,對於微博的爬蟲,大部分是基於模擬微博賬號登入的方式實現的,這種方式如果真的運營起來,實際上是一件非常頭疼痛苦的事,你可能每天都過得提心吊膽,生怕新浪爸爸把你的那些賬號給封了,而且現在隨著實名制的落地,獲得賬號的渠道估計也會變得越來越少。

但是日子還得繼續,在如此艱難的條件下,為了生存爬蟲們必須尋求進化。

好在上帝關門的同時會隨手開窗,微博在其他諸如頭條,一點等這類新媒體平臺的衝擊之下,逐步放開了資訊流的檢視許可權。

現在的微博即便在不登入的狀態下,依然可以看到很多微博資訊流,而我們的落腳點就在這裡。

作為前篇的重點內容,本文詳細介紹如何獲取相關的Cookie並重新封裝Httpclient達到免登入的目的,以支援微博上的各項資料抓取任務。

下面就從微博首頁http://weibo.com開始。

二、準備工作 準備工作很簡單,一個現代瀏覽器(你知道我為什麼會寫”現代”兩個字),以及httpclient(我用的版本是4.5.3) 跟登入爬蟲一樣,免登入爬蟲也是需要裝載Cookie。

這裡的Cookie是用來標明遊客身份,利用這個Cookie就可以在微博平臺中訪問那些允許訪問的內容了。

這裡我們可以使用瀏覽器的network工具來看一下,請求http://weibo.com之後伺服器都返回哪些東西,當然事先清空一下瀏覽器的快取。

不出意外,應該可以看到下圖中的內容 第1次請求weibo.com的時候,其狀態為302重定向,也就是說這時並沒有真正地開始載入頁面,而最後一個請求weibo.com的狀態為200,表示了請求成功,對比兩次請求的header: 明顯地,中間的這些過程給客戶端載入了各種Cookie,從而使得可以順利訪問頁面,接下來我們逐個進行分析。

三、抽絲剝繭 第2個請求是https://passport.weibo.com/visitor……,各位可以把這個url複製出來,用httpclient單獨訪問一下這個url,可以看到返回的是一個html頁面,裡面有一大段Javascript指令碼,另外頭部還引用一個JS檔案mini_original.js,也就是第3個請求。

指令碼的功能比較多,就不一一敘述了,簡單來說就是微博訪問的入口控制,而值得我們注意的是其中的一個function: JavaScript. //為使用者賦予訪客身份。

varincarnate=function(tid,where,conficence){ vargenconf=""; varfrom="weibo"; varincarnate_intr=window.location.protocol+"//"+window.location.host+"/visitor/visitor?a=incarnate&t="+encodeURIComponent(tid)+"&w="+encodeURIComponent(where)+"&c="+encodeURIComponent(conficence)+"&gc="+encodeURIComponent(gen_conf)+"&cb=cross_domain&from="+from+"&_rand="+Math.random(); url.l(incarnate_intr); }; 1234567 //為使用者賦予訪客身份。

varincarnate=function(tid,where,conficence){vargenconf="";varfrom="weibo";varincarnate_intr=window.location.protocol+"//"+window.location.host+"/visitor/visitor?a=incarnate&t="+encodeURIComponent(tid)+"&w="+encodeURIComponent(where)+"&c="+encodeURIComponent(conficence)+"&gc="+encodeURIComponent(gen_conf)+"&cb=cross_domain&from="+from+"&_rand="+Math.random();url.l(incarnate_intr);}; 這裡是為請求者賦予一個訪客身份,而控制跳轉的連結也是由一些引數拼接起來的,也就是上圖中第6個請求。

所以下面的工作就是獲得這3個引數:tid,w(where),c(conficence,從下文來看應為confidence,大概是新浪工程師的手誤)。

繼續閱讀原始碼,可以看到該function是tid.get方法的回撥函式,而這個tid則是定義在那個mini_original.js中的一個物件,其部分原始碼為: JavaScript vartid={ key:'tid', value:'', recover:0, confidence:'', postInterface:postUrl, fpCollectInterface:sendUrl, callbackStack:[], init:function(){ tid.get(); }, runstack:function(){ varf; while(f=tid.callbackStack.pop()){ f(tid.value,tid.recover,tid.confidence);//注意這裡,對應上述的3個引數 } }, get:function(callback){ callback=callback||function(){ }; tid.callbackStack.push(callback); if(tid.value){ returntid.runstack(); } Store.DB.get(tid.key,function(v){ if(!v){ tid.getTidFromServer(); }else{ …… } }); }, …… } …… getTidFromServer:function(){ tid.getTidFromServer=function(){ }; if(window.usefp){ getFp(function(data){ util.postData(window.location.protocol+'//'+window.location.host+'/'+tid.postInterface,"cb=gen_callback&fp="+encodeURIComponent(data),function(res){ if(res){ eval(res); } }); }); }else{ util.postData(window.location.protocol+'//'+window.location.host+'/'+tid.postInterface,"cb=gen_callback",function(res){ if(res){ eval(res); } }); } }, …… //獲得引數 window.gen_callback=function(fp){ varvalue=false,confidence; if(fp){ if(fp.retcode==20000000){ confidence=typeof(fp.data.confidence)!='undefined'?'000'+fp.data.confidence:'100'; tid.recover=fp.data.new_tid?3:2; tid.confidence=confidence=confidence.substring(confidence.length-3); value=fp.data.tid; Store.DB.set(tid.key,value+''+confidence); } } tid.value=value; tid.runstack(); }; 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 vartid={key:'tid',value:'',recover:0,confidence:'',postInterface:postUrl,fpCollectInterface:sendUrl,callbackStack:[],init:function(){tid.get();},runstack:function(){varf;while(f=tid.callbackStack.pop()){f(tid.value,tid.recover,tid.confidence);//注意這裡,對應上述的3個引數}},get:function(callback){callback=callback||function(){};tid.callbackStack.push(callback);if(tid.value){returntid.runstack();}Store.DB.get(tid.key,function(v){if(!v){tid.getTidFromServer();}else{……}});},……}……getTidFromServer:function(){tid.getTidFromServer=function(){};if(window.usefp){getFp(function(data){util.postData(window.location.protocol+'//'+window.location.host+'/'+tid.postInterface,"cb=gen_callback&fp="+encodeURIComponent(data),function(res){if(res){eval(res);}});});}else{util.postData(window.location.protocol+'//'+window.location.host+'/'+tid.postInterface,"cb=gen_callback",function(res){if(res){eval(res);}});}},……//獲得引數window.gen_callback=function(fp){varvalue=false,confidence;if(fp){if(fp.retcode==20000000){confidence=typeof(fp.data.confidence)!='undefined'?'000'+fp.data.confidence:'100';tid.recover=fp.data.new_tid?3:2;tid.confidence=confidence=confidence.substring(confidence.length-3);value=fp.data.tid;Store.DB.set(tid.key,value+''+confidence);}}tid.value=value;tid.runstack();}; 顯然,tid.runstack()是真正執行回撥函式的地方,這裡就能看到傳入的3個引數。

在get方法中,當cookie為空時,tid會呼叫getTidFromServer,這時就產生了第5個請求https://passport.weibo.com/visitor/genvisitor,它需要兩個引數cb和fp,其引數值可以作為常量: 該請求的結果返回一串json JavaScript { "msg":"succ", "data":{ "new_tid":false, "confidence":95, "tid":"kIRvLolhrCR5iSCc80tWqDYmwBvlRVlnY2+yvCQ1VVA=" }, "retcode":20000000 } 123456789 {"msg":"succ","data":{"new_tid":false,"confidence":95,"tid":"kIRvLolhrCR5iSCc80tWqDYmwBvlRVlnY2+yvCQ1VVA="},"retcode":20000000} 其中就包含了tid和confidence,這個confidence,我猜大概是推測客戶端是否真實的一個置信度,不一定出現,根據window.gen_callback方法,不出現時預設為100,另外當new_tid為真時引數where等於3,否則等於2。

此時3個引數已經全部獲得,現在就可以用httpclient發起上面第6個請求,返回得到另一串json: JavaScript { "msg":"succ", "data":{ "sub":"_2AkMu428tf8NxqwJRmPAcxWzmZYh_zQjEieKYv572JRMxHRl-yT83qnMGtRCnhyR4ezQQZQrBRO3gVMwM5ZB2hQ..", "subp":"0033WrSXqPxfM72-Ws9jqgMF55529P9D9WWU2MgYnITksS2awP.AX-DQ" }, "retcode":20000000 } 12345678 {"msg":"succ","data":{"sub":"_2AkMu428tf8NxqwJRmPAcxWzmZYh_zQjEieKYv572JRMxHRl-yT83qnMGtRCnhyR4ezQQZQrBRO3gVMwM5ZB2hQ..","subp":"0033WrSXqPxfM72-Ws9jqgMF55529P9D9WWU2MgYnITksS2awP.AX-DQ"},"retcode":20000000} 參考最後請求weibo.com的header,這裡的sub和subp就是最終要獲取的cookie值。

大家或許有一個小疑問,第一個Cookie怎麼來的,沒用嗎?是的,這個Cookie是第一次訪問weibo.com產生的,經過測試可以不用裝載。

最後我們用上面兩個Cookie裝載到HttpClient中請求一次weibo.com,就可以獲得完整的html頁面了,下面就是見證奇蹟的時刻: XHTML

try{document.execCommand("BackgroundImageCache",false,true);}catch(e){} 微博-隨時隨地發現新鮮事 var$CONFIG={}; $CONFIG['islogin']='0'; $CONFIG['version']='6c9bf6ab3b33391f'; $CONFIG['timeDiff']=(newDate()-1505746970000); $CONFIG['lang']='zh-cn'; $CONFIG['jsPath']='//js.t.sinajs.cn/t5/'; $CONFIG['cssPath']='//img.t.sinajs.cn/t5/'; $CONFIG['imgPath']='//img.t.sinajs.cn/t5/'; $CONFIG['servertime']=1505746970; $CONFIG['location']='login'; $CONFIG['bigpipe']='false'; $CONFIG['bpType']='login'; $CONFIG['mJsPath']=['//js{n}.t.sinajs.cn/t5/',1,2]; $CONFIG['mCssPath']=['//img{n}.t.sinajs.cn/t5/',1,2]; $CONFIG['redirect']=''; $CONFIG['vid']='1008997495870'; …… 12345678910111213141516171819202122232425262728293031323334353637 try{document.execCommand("BackgroundImageCache",false,true);}catch(e){}微博-隨時隨地發現新鮮事 var$CONFIG={};$CONFIG['islogin']='0';$CONFIG['version']='6c9bf6ab3b33391f';$CONFIG['timeDiff']=(newDate()-1505746970000);$CONFIG['lang']='zh-cn';$CONFIG['jsPath']='//js.t.sinajs.cn/t5/';$CONFIG['cssPath']='//img.t.sinajs.cn/t5/';$CONFIG['imgPath']='//img.t.sinajs.cn/t5/';$CONFIG 談談微信支付曝出的漏洞 «上一篇 搜尋引擎原理及使用下一篇» 相關推薦 微博爬蟲“免登入”技巧詳解及Java實現 一、微博一定要登入才能抓取? 目前,對於微博的爬蟲,大部分是基於模擬微博賬號登入的方式實現的,這種方式如果真的運營... Keras入門教程06——CapsNet膠囊神經網路詳解及Keras實現 論文《DynamicRoutingBetweenCapsules》 參考了一篇部落格還有Keras官方的... 爬蟲------github登入 爬蟲------github登入 importrequests frombs4importBeautifulSoup r1=... 新浪微博爬蟲v1.0             ... 微博第三方登入使用social_django實現顯示登陸的使用者名稱 首先修改social_soce原始碼,將使用者資訊新增進cookie    將其修改為:  ... 1-新浪微博爬蟲-(2017-05-09) 1爬使用者的資訊 1-1哪裡找cooki... 新浪微博第三方登入 填寫安全域名,本地測試的話可以改hosts檔案指向相應的域名  這裡也填上 (1)使用後端實現第三方登入 ... 求助微博爬蟲,python中BeautifulSoup之後的select()返回空字串 frombs4importBeautifulSoup importrequests importre headers... 楊超越微博爬蟲(微博文字+圖片)粉絲資訊待續 #-*-coding:utf-8-*- importurllib.request importjson importtime import... 騰訊QQ、新浪微博第三方登入介面申請說明 這一段時間,公司一直要求在網站上加入第三方登入功... 搜尋 基礎教學 Mysql入門 Sql入門 Android入門 Docker入門 Go語言入門 Ruby程式入門 Python入門 Python進階 Django入門 Python爬蟲入門 最近訪問 微博爬蟲“免登入”技巧詳解及+Java+實現 [轉載]ValidationExpression驗證規則 【C語言】建立動態陣列 Git學習之路(三)-branch、checkout、pull命令的使用 C++庫常用函式一覽 python+bind()方法 String[]和List的區別及相互轉換 [洛谷P1750]KC喝咖啡 Hadoop問題:+沒有到主機的路由 樹莓派3攝像頭使用--python


請為這篇文章評分?