最近在用PHP抓取各種IP資料,這裡講一下在抓取百度百科資料時的步驟以及遇到的坑。
首先我們要確定抓取的內容是什麼。比如我們想抓取“周杰倫”的資料。我們直接在百度搜尋周杰倫,會出現百度的搜尋結果,其中就有百度百科的內容,我們直接點進去。
我們先看一下我們搜尋結果的百度百科URL是什麼樣子的:
可以看到格式為http://baike.baidu.com/link?url=params
其中這個params其實就是urlencode我們搜尋的關鍵字之後形成的參數,所以我們可以根據前端直接POST過來的關鍵字進行URL的拼接之後用CURL或者phpQuery來抓取百度百科頁面的資訊。但是這裡有一個問題。我們搜尋出來的關鍵字的百科資訊可能對應了不同的詞條。比如我們搜尋了“仙劍奇俠傳“,我們本意想搜尋胡歌主演的電視劇,但是百科的第一詞條卻是顯示的仙劍奇俠傳這個遊戲,這個詞條是一個多義詞。所以我們前端傳過來的值最好是確定的百度百科URL,這樣我們抓取的資訊會準確無誤。
好了現在有了URL了,我們下面就要開始抓取我們想要的資料了。最想要的資料應該就是我們搜尋出來的詞條的基本資料,就是圖下的內容:
周杰倫是名人,你可按照詞條的分類不同建立不同的資料表,比如人物一張表,影視內容一張表等等,因為同一類的百科基本資料組成都差不多。如果用NoSQL就更方便了,直接把這些資訊全放進去就可以。
抓取頁面一部分的內容還是用phpQuery比較方便,我們先看一下這個基本資料的DOM元素:
可以看到這個是一個basic-info為class的div包裹的,左邊的資訊在basicInfo-left中,右邊的資訊在basicInfo-right中。具體的資訊在一個dt和dd組成的元素裡,一個資訊(在.basicInfo-item name的class)對應一個值(在basicInfo-item value的class中)。
我們直接把這個class為basic-info的div裡面的html抓取下來就好,剩下我們在用正則匹配我們想要的內容。
直接pq('.basic-info')->html()就可以了。
我們先看一下抓取到的內容是什麼樣子的:
基本上就是一個原始的HTML內容。我們要正則匹配出來我們想要的資訊然後存入相應的欄位中。
我們先把這個字串裡的空格都清楚掉,方便我們的正則匹配,我這裡寫了一個函數:
。注意:可以看到我最後還替換了一個\x{00a0}的東西,這個是什麼呢。這個就是一個坑。大家可以在上面的HTML圖中看到,其中資訊為兩個字的中間有四個空格,但是這個空格並不能用平常的空格給代替掉,必須用ASCII碼來替換,這是需要注意的。
接下來正則匹配我們想要的資訊:
這裡也要注意,有些我們想要的資訊是有多個資訊匹配的,雖然名字不一樣,但是裡面資訊的內容卻是相近的。這裡舉例的是明星和運動演員,都是獲得的獎項,但是名字卻不一樣。同樣的還有電影的票房,票房、全球票房、統計票房等等,其實都是票房的欄位資訊,隨意抓取的時候多觀察幾個百科頁面的資訊,做到萬無一失。
然後將匹配到的資訊存到數組中準備插入資料庫,在插入資料庫之前還有一個工作要做:
我們要把數組中的標籤、注釋和多餘資訊給剔除。
注釋是這樣的:
多餘資訊是這樣的:
這些都是要注意的內容。
最後我們就得到了我們想要的資料了,分類插入資料庫就OK啦。