PHP使用DOMDocument採集

技術小牛人發表於2017-11-12

採集是很多公司都做最的一件事,能夠快速的獲取別人辛苦得來的資料,雖為不道義,但無法禁止!


PHP採集一般方式有:

  1. 正則採集。

  2. 使用DOM物件採集。

  3. 使用字串函式提取。


這裡只說下DOM物件採集的一些問題:


PHP有DOM物件專門用來處理HTML或XML檔案,非常方便。

1
2
3
$dom new DOMDocument(`1.0`,`GBK`);//建立DOM物件
@$dom->loadHTMLFile($url);//載入對應的URL地址HTML內容
$xpath=new DOMXPath($dom);//建立DOMXPath物件

DOMXPath物件是一個支援 XPath 路徑表示式,http://www.w3school.com.cn/xpath/

XPath 路徑表示式類似 JQuery選擇器一樣,可以方便的找到對應的節點然後提取內容,當然 XPath 的選擇方式要遠比 JQuery 多。而且還支援很多種函式處理。


注意

1
@$dom->loadHTMLFile($url);//載入對應的URL地址HTML內容

這句程式碼前面最好加上 @ 符號,因為在載入解析HTML內容時,或多或少會出現錯誤,如:在HTML頁面內一些 & 符號要轉義成 & ,html實體符號必須以 ;結束等等 才能順利解析。而這類要求在採集過程中是不可能的。


採集過程中最讓人麻煩的是中文字元處理,使用正則採集時,中文字元加在正則內雖然方便但容易出錯,正則中寫入中文必須保證被採集的字符集與當前系統程式碼字符集是相同的,否則匹配很容易失敗。

使用DOMDocument解析HTML內容,也容易出現中文問題,一般是亂碼,其主要原因是HTML結構不標準,

出現亂碼都是字符集的問題,一般在HTML的head標籤要指定字符集

<meta http-equiv=Content-Type content=”text/html;charset=gb2312″>

當這個標籤不存在時,DOMDocument在解析時就會以預設的方式去解析這個HTML內容,導致中文編碼錯誤。


所以在使用DOMDocument採集時不要直接使用

1
@$dom->loadHTMLFile($url);//載入對應的URL地址HTML內容

方式直接載入HTML,這樣只要所採集的HTML內容沒有包含字符集的指定,整個HTML內容解析後中文就不能用。

最好使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ch = curl_init($url);//建立連線
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);//輸出內容
curl_setopt($ch, CURLOPT_TIMEOUT, 10);//設定超時時間
$html =  curl_exec($ch);//執行連線,獲取內容
if($err=curl_error($ch)){//判斷是否出錯
   die($err);
}else{
    //判斷是否存在這個標籤
   if(!stripos(`"Content-Type"`$html)&&!stripos(`content="text/html;`$html)){
       $meta=`<head><meta http-equiv="Content-Type" content="text/html; charset=GBK" />`;
       $html=str_replace(`<head>`$meta$html);
   }
}
curl_close($ch);
$dom new DOMDocument(`1.0`,`GBK`);//建立DOM物件
@$dom->loadHTML($html);//載入對應的URL地址HTML內容
$xpath=new DOMXPath($dom);//建立DOMXPath物件

對應所採集的頁面字符集,必須核對好。

DOMXPath有兩個函式用來操作內部節點:

query,和evaluate

query:取出給定的XPath表示式節點列表,只要表示式合法,返回DOMNodeList物件,否則返回false。

evaluate:取出給定XPath表示式節點列表,只要表示式合法並且有匹配的節點返回DOMNodeList物件,否則返回false。


兩個函式都是提取節點,只是返回值上有些區別。

DOMNodeList 物件有一個函式和一個屬性:

/* 屬性,節點列表個數 */

readonly publicint $length ;

/* 方法獲取第幾個節點 */

DOMNode DOMNodelist::item ( int $index )


使用item函式獲取的節點 DOMElement 物件 ,

可以使用 getAttribute 獲取節點屬性值,也可以使用 nodeValue 屬性獲取節點內容。

本文轉自  ttlxihuan    51CTO部落格,原文連結:http://blog.51cto.com/php2012web/1619260


相關文章