【php爬蟲(chóng)】百萬(wàn)級別知乎用戶(hù)數據爬取與剖析
優(yōu)采云 發(fā)布時(shí)間: 2020-06-14 08:03代碼托管地址:
文/Hector
這次抓取了110萬(wàn)的用戶(hù)數據php 網(wǎng)絡(luò )爬蟲(chóng) 抓取數據,數據剖析結果如下:
開(kāi)發(fā)前的打算
安裝linux系統(Ubuntu14.04),在VMWare虛擬機下安裝一個(gè)Ubuntu;
安裝PHP5.6或以上版本;
安裝curl、pcntl擴充。
使用PHP的curl擴充抓取頁(yè)面數據
PHP的curl擴充是PHP支持的容許你與各類(lèi)服務(wù)器使用各類(lèi)類(lèi)型的合同進(jìn)行聯(lián)接和通訊的庫。
本程序是抓取知乎的用戶(hù)數據,要能訪(fǎng)問(wèn)用戶(hù)個(gè)人頁(yè)面,需要用戶(hù)登陸后的能夠訪(fǎng)問(wèn)。當我們在瀏覽器的頁(yè)面中點(diǎn)擊一個(gè)用戶(hù)頭像鏈接步入用戶(hù)個(gè)人中心頁(yè)面的時(shí)侯,之所以還能看見(jiàn)用戶(hù)的信息,是因為在點(diǎn)擊鏈接的時(shí)侯,瀏覽器幫你將本地的cookie帶上一同遞交到新的頁(yè)面,所以你才能步入到用戶(hù)的個(gè)人中心頁(yè)面。因此實(shí)現訪(fǎng)問(wèn)個(gè)人頁(yè)面之前須要先獲得用戶(hù)的cookie信息,然后在每次curl懇求的時(shí)侯帶上cookie信息。在獲取cookie信息方面,我是用了自己的cookie,在頁(yè)面中可以看見(jiàn)自己的cookie信息:
一個(gè)個(gè)地復制,以"__utma=?;__utmb=?;"這樣的方式組成一個(gè)cookie字符串。接下來(lái)就可以使用該cookie字符串來(lái)發(fā)送懇求。
初始的示例:
$url = ''; <br /> //此處mora-hu代表用戶(hù)ID
$ch = curl_init($url); <br /> //初始化會(huì )話(huà)
curl_setopt($ch, CURLOPT_HEADER, 0); <br /> curl_setopt($ch, CURLOPT_COOKIE, $this->config_arr['user_cookie']); <br /> //設置請求COOKIE
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); <br /> curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); <br /> //將curl_exec()獲取的信息以文件流的形式返回,而不是直接輸出。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); <br /> $result = curl_exec($ch); <br /> return $result; //抓取的結果
運行里面的代碼可以獲得mora-hu用戶(hù)的個(gè)人中心頁(yè)面。利用該結果再使用正則表達式對頁(yè)面進(jìn)行處理,就能獲取到姓名,性別等所須要抓取的信息。
圖片防盜鏈
在對返回結果進(jìn)行正則處理后輸出個(gè)人信息的時(shí)侯,發(fā)現在頁(yè)面中輸出用戶(hù)頭像時(shí)難以打開(kāi)。經(jīng)過(guò)查閱資料獲知,是因為知乎對圖片做了防盜鏈處理。解決方案就是懇求圖片的時(shí)侯在懇求頭里偽造一個(gè)referer。
在使用正則表達式獲取到圖片的鏈接以后,再發(fā)一次懇求,這時(shí)候帶上圖片懇求的來(lái)源,說(shuō)明該懇求來(lái)自知乎網(wǎng)站的轉發(fā)。具體事例如下:
function getImg($url, $u_id){ <br /> if (file_exists('./images/' . $u_id . ".jpg")) <br /> { <br /> return "images/$u_id" . '.jpg'; } if (empty($url)) <br /> { <br /> return ''; <br /> }<br /> $context_options = array( <br /> 'http' =>
array(<br /> 'header' => "Referer:"//帶上referer參數
)<br /> );<br /> $context = stream_context_create($context_options);<br /> $img = file_get_contents('http:' . $url, FALSE, $context);<br /> file_put_contents('./images/' . $u_id . ".jpg", $img);<br /> return "images/$u_id" . '.jpg';}
爬取更多用戶(hù)
抓取了自己的個(gè)人信息后,就須要再訪(fǎng)問(wèn)用戶(hù)的關(guān)注者和關(guān)注了的用戶(hù)列表獲取更多的用戶(hù)信息。然后一層一層地訪(fǎng)問(wèn)??梢砸?jiàn)到,在個(gè)人中心頁(yè)面里,有兩個(gè)鏈接如下:
這里有兩個(gè)鏈接,一個(gè)是關(guān)注了,另一個(gè)是關(guān)注者,以“關(guān)注了”的鏈接為例。用正則匹配去匹配到相應的鏈接,得到url以后用curl帶上cookie再發(fā)一次懇求。抓取到用戶(hù)關(guān)注了的用于列表頁(yè)以后,可以得到下邊的頁(yè)面:
分析頁(yè)面的html結構php 網(wǎng)絡(luò )爬蟲(chóng) 抓取數據,因為只要得到用戶(hù)的信息,所以只須要框住的這一塊的div內容,用戶(hù)名都在這上面??梢钥匆?jiàn),用戶(hù)關(guān)注了的頁(yè)面的url是:
不同的用戶(hù)的這個(gè)url幾乎是一樣的,不同的地方就在于用戶(hù)名哪里。用正則匹配領(lǐng)到用戶(hù)名列表,一個(gè)一個(gè)地拼url,然后再挨個(gè)發(fā)懇求(當然,一個(gè)一個(gè)是比較慢的,下面有解決方案,這個(gè)稍后會(huì )說(shuō)到)。進(jìn)入到新用戶(hù)的頁(yè)面然后,再重復前面的步驟,就這樣不斷循環(huán),直到達到你所要的數據量。


