【php爬蟲(chóng)】百萬(wàn)級(jí)別知乎用戶數(shù)據(jù)爬取與分析

2015-09-30 10:16:00 來(lái)源:cnblogs.com 作者:佚名 人氣: 次閱讀 360 條評(píng)論

本程序是抓取知乎的用戶數(shù)據(jù),要能訪問(wèn)用戶個(gè)人頁(yè)面,需要用戶登錄后的才能訪問(wèn)。當(dāng)我們?cè)跒g覽器的頁(yè)面中點(diǎn)擊一個(gè)用戶頭像鏈接進(jìn)入用戶個(gè)人中心頁(yè)面的時(shí)候,之所以能夠看到...

這次抓取了110萬(wàn)的用戶數(shù)據(jù),數(shù)據(jù)分析結(jié)果如下:

PHP爬蟲(chóng) 數(shù)據(jù)抓取 數(shù)據(jù)分析 爬蟲(chóng)抓取數(shù)據(jù)

開(kāi)發(fā)前的準(zhǔn)備

安裝linux系統(tǒng)(Ubuntu14.04),在VMWare虛擬機(jī)下安裝一個(gè)Ubuntu;

安裝PHP5.6或以上版本;

安裝curl、pcntl擴(kuò)展。

使用PHP的curl擴(kuò)展抓取頁(yè)面數(shù)據(jù)

PHP的curl擴(kuò)展是PHP支持的允許你與各種服務(wù)器使用各種類型的協(xié)議進(jìn)行連接和通信的庫(kù)。

本程序是抓取知乎的用戶數(shù)據(jù),要能訪問(wèn)用戶個(gè)人頁(yè)面,需要用戶登錄后的才能訪問(wèn)。當(dāng)我們?cè)跒g覽器的頁(yè)面中點(diǎn)擊一個(gè)用戶頭像鏈接進(jìn)入用戶個(gè)人中心頁(yè)面的時(shí)候,之所以能夠看到用戶的信息,是因?yàn)樵邳c(diǎn)擊鏈接的時(shí)候,瀏覽器幫你將本地的cookie帶上一齊提交到新的頁(yè)面,所以你就能進(jìn)入到用戶的個(gè)人中心頁(yè)面。因此實(shí)現(xiàn)訪問(wèn)個(gè)人頁(yè)面之前需要先獲得用戶的cookie信息,然后在每次curl請(qǐng)求的時(shí)候帶上cookie信息。在獲取cookie信息方面,我是用了自己的cookie,在頁(yè)面中可以看到自己的cookie信息:

PHP爬蟲(chóng) 數(shù)據(jù)抓取 數(shù)據(jù)分析 爬蟲(chóng)抓取數(shù)據(jù)

一個(gè)個(gè)地復(fù)制,以"__utma=?;__utmb=?;"這樣的形式組成一個(gè)cookie字符串。接下來(lái)就可以使用該cookie字符串來(lái)發(fā)送請(qǐng)求。

初始的示例:

    $url = 'http://www.zhihu.com/people/mora-hu/about'; 
//
此處mora-hu代表用戶ID $ch = curl_init($url);
//
初始化會(huì)話 curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt(
$ch, CURLOPT_COOKIE, $this->config_arr['user_cookie']);
//
設(shè)置請(qǐng)求COOKIE curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt(
$ch, CURLOPT_RETURNTRANSFER, 1); //將curl_exec()獲取的信息以文件流的形式返回,而不是直接輸出。 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$result = curl_exec($ch);
return
$result; //抓取的結(jié)果

運(yùn)行上面的代碼可以獲得mora-hu用戶的個(gè)人中心頁(yè)面。利用該結(jié)果再使用正則表達(dá)式對(duì)頁(yè)面進(jìn)行處理,就能獲取到姓名,性別等所需要抓取的信息。

圖片防盜鏈

在對(duì)返回結(jié)果進(jìn)行正則處理后輸出個(gè)人信息的時(shí)候,發(fā)現(xiàn)在頁(yè)面中輸出用戶頭像時(shí)無(wú)法打開(kāi)。經(jīng)過(guò)查閱資料得知,是因?yàn)橹鯇?duì)圖片做了防盜鏈處理。解決方案就是請(qǐng)求圖片的時(shí)候在請(qǐng)求頭里偽造一個(gè)referer。

在使用正則表達(dá)式獲取到圖片的鏈接之后,再發(fā)一次請(qǐng)求,這時(shí)候帶上圖片請(qǐng)求的來(lái)源,說(shuō)明該請(qǐng)求來(lái)自知乎網(wǎng)站的轉(zhuǎn)發(fā)。具體例子如下:

function getImg($url, $u_id){    
if (file_exists('./images/' . $u_id . ".jpg"))
{
return "images/$u_id" . '.jpg'; } if (empty($url))
{
return '';
}
$context_options = array(
'http' => array(
'header' => "Referer:http://www.zhihu.com"//帶上referer參數(shù)   )
  );
$context = stream_context_create($context_options);
$img = file_get_contents('http:' . $url, FALSE, $context);
file_put_contents('./images/' . $u_id . ".jpg", $img);
return "images/$u_id" . '.jpg';}

爬取更多用戶

抓取了自己的個(gè)人信息后,就需要再訪問(wèn)用戶的關(guān)注者和關(guān)注了的用戶列表獲取更多的用戶信息。然后一層一層地訪問(wèn)。可以看到,在個(gè)人中心頁(yè)面里,有兩個(gè)鏈接如下:

PHP爬蟲(chóng) 數(shù)據(jù)抓取 數(shù)據(jù)分析 爬蟲(chóng)抓取數(shù)據(jù)

這里有兩個(gè)鏈接,一個(gè)是關(guān)注了,另一個(gè)是關(guān)注者,以“關(guān)注了”的鏈接為例。用正則匹配去匹配到相應(yīng)的鏈接,得到url之后用curl帶上cookie再發(fā)一次請(qǐng)求。抓取到用戶關(guān)注了的用于列表頁(yè)之后,可以得到下面的頁(yè)面:

PHP爬蟲(chóng) 數(shù)據(jù)抓取 數(shù)據(jù)分析 爬蟲(chóng)抓取數(shù)據(jù)

分析頁(yè)面的html結(jié)構(gòu),因?yàn)橹灰玫接脩舻男畔ⅲ灾恍枰蜃〉倪@一塊的div內(nèi)容,用戶名都在這里面。可以看到,用戶關(guān)注了的頁(yè)面的url是:

PHP爬蟲(chóng) 數(shù)據(jù)抓取 數(shù)據(jù)分析 爬蟲(chóng)抓取數(shù)據(jù)

不同的用戶的這個(gè)url幾乎是一樣的,不同的地方就在于用戶名那里。用正則匹配拿到用戶名列表,一個(gè)一個(gè)地拼url,然后再逐個(gè)發(fā)請(qǐng)求(當(dāng)然,一個(gè)一個(gè)是比較慢的,下面有解決方案,這個(gè)稍后會(huì)說(shuō)到)。進(jìn)入到新用戶的頁(yè)面之后,再重復(fù)上面的步驟,就這樣不斷循環(huán),直到達(dá)到你所要的數(shù)據(jù)量。

您可能感興趣的文章

相關(guān)文章