【php爬蟲】百萬級別知乎用戶數(shù)據(jù)爬取與分析

2015-09-30 10:16:00 來源:cnblogs.com 作者:佚名 人氣: 次閱讀 360 條評論

本程序是抓取知乎的用戶數(shù)據(jù),要能訪問用戶個人頁面,需要用戶登錄后的才能訪問。當我們在瀏覽器的頁面中點擊一個用戶頭像鏈接進入用戶個人中心頁面的時候,之所以能夠看到...

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

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

開發(fā)前的準備

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

安裝PHP5.6或以上版本;

安裝curl、pcntl擴展。

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

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

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

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

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

初始的示例:

    $url = 'http://www.zhihu.com/people/mora-hu/about'; 
//
此處mora-hu代表用戶ID $ch = curl_init($url);
//
初始化會話 curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt(
$ch, CURLOPT_COOKIE, $this->config_arr['user_cookie']);
//
設(shè)置請求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é)果

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

圖片防盜鏈

在對返回結(jié)果進行正則處理后輸出個人信息的時候,發(fā)現(xiàn)在頁面中輸出用戶頭像時無法打開。經(jīng)過查閱資料得知,是因為知乎對圖片做了防盜鏈處理。解決方案就是請求圖片的時候在請求頭里偽造一個referer。

在使用正則表達式獲取到圖片的鏈接之后,再發(fā)一次請求,這時候帶上圖片請求的來源,說明該請求來自知乎網(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';}

爬取更多用戶

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

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

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

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

分析頁面的html結(jié)構(gòu),因為只要得到用戶的信息,所以只需要框住的這一塊的div內(nèi)容,用戶名都在這里面??梢钥吹?,用戶關(guān)注了的頁面的url是:

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

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