PHP版的jQuery

jopen 10年前發布 | 28K 次閱讀 jQuery PHP開發

個人認為,對于Web前端程序員和跟HTML和CSS打交道的人來說,jQuery是有史以來最偉大的發明。jQuery的出現使Web程序員的開發效率突飛猛進,不亞于工業革命給人類生產力帶來的提升。

但問題在在于,只有前端程序員可以利用jQuery的強力,他們可以用它分析HTML,根據CCS類,HTML屬性,CSS規則等各種選擇器來查詢、獲取、操作HTML里的任何一個元素。而作為后端(服務端)程序員來說,他們同樣需要分析HTML內容,從HTML中提取符合要求的HTML片段、獲取某個符合條件的屬性值等。

遇到這種情況,后端程序員通常的做法就是用正則表達式、或用XML解析器。這些做法非常的笨拙,不方便,效率低下。所以,對于在服務器端解析HTML,每個后端程序員都極力避免。

我是一個PHP程序員,最近就遇到了這樣的一個任務,需要在服務器端解析HTML,將里面的標題名稱和鏈接提取出來。最初我想開發一個小程序逐行分析HTML,捕捉關鍵字,或用正則表達式。但簡單分析了一下,這樣做實在不可取。因為我也是個Web程序員,經常使用jQuery解析HTML頁面上的內容。如果這個任務放到瀏覽器端執行,太簡單了,只需要一句代碼:jQuery('.title').each(...);,如何能在服務器端也能像jQuery那樣進行HTML DOM查詢呢?

實際上,在服務器端有不少具有jQuery功能的PHP程序庫。在網上稍微做了點功夫,就搜到了10幾個聲稱都能解析HTML的PHP工具。但經過試驗,大部分都多少有這樣或那樣的缺陷,而且都有一個通病,就是中文亂碼問題。最終,我選用了一個叫做phpQuery的工具包。

實際上,使用phpQuery這個PHP程序庫也是很不情愿的,因為這個程序已經很多年沒人維護更新了。但比起其它幾個類似功能程序庫,例如Zend_DomQueryPathSimpleHtmlDom,它算是好的。

phpQuery的接口很豐富,但很簡單。一個基本的用法是這樣的:

$list = phpQuery::newDocumentFileHTML('http://www.webhek.com')->find('h2.title a');
foreach($list as $e) { 
    $title = $e->nodeValue;
    $url = $e->getAttribute('href');
}

上面的find()方法返回的對象是PHP官方擴展庫中的DOM對象,也就是說,phpQuery是一個基于PHP原生的DOM對象的HTML/XML解析器,這樣做的好處是,效率很高。相反,像SimpleHtmlDom這樣也是分析HTML/XML的程序庫,但沒有基于PHP原生DOM對象,當分析大數據量時,很容易產生性能問題,所以不推薦使用。

之前說了,所有的這樣類似jQuery的能分析HTML DOM的PHP程序庫都一個相同的通病:遇到中文會有亂碼。我在使用phpQuery的過程中也遇到了這個問題。

首先PHP中的中文本身就是個問題,而PHP的DOM對象處理中文的方式也是有爭議的。官方文檔是說,這個DOM擴展包使用的是UTF-8編碼,當遇到 ISO-8859-1 編碼的文本時,使用 utf8_encode() 和 utf8_decode() 編碼和解碼,遇到其它編碼時,使用Iconv函數進行轉碼。但現實情況比這要復雜的多。網上有很多意見認為在遇到DOM亂碼時,在HTML代碼里的<title>標記前加入<meta charset="utf-8">就行了。但這種方法有時候也不靈。

我在解決phpQuery的中文亂碼問題也是反復嘗試才最后搞定的,沒有任何理論依據。就像是有個程序員的笑話:這段代碼不好用,我不知道為什么。這段代碼好用,我也不知道為什么。:(

首先我是在臺式機上開發測試的,是Window7,這種環境下會出現兩種情況,一種情況是HTML的字符集是GBK/gb2312,一種情況是字符集是UTF-8。奇怪的是,兩個同樣是gb2312字符集的不同頁面,用phpQuery解析后,一個會有亂碼,一個沒有亂碼。同樣,兩個同樣是UTF-8字符集的不同頁面,也會出現這種情況。所有,對我來說,沒有規律可言。我只能說,這兩種方法能解決phpQuery使用過程中出現的亂碼,但何時使用哪種?我不知道,你只能兩個都試一下,會有一個好用。

所以,有亂碼出現時,首先使用第一種方案:

//仍然使用上面的代碼例子:
$list = phpQuery::newDocumentFileHTML('http://www.webhek.com')->find('h2.title a');
foreach($list as $e) { 
    $title = $e->nodeValue;
    //進行GBK轉碼
    $title = iconv("UTF-8","GBK",  $title);
}

如果不行,使用第二種方案:

//仍然使用上面的代碼例子:
//指定GBK字符集參數
$list = phpQuery::newDocumentFileHTML('http://www.webhek.com','GBK')->find('h2.title a');
foreach($list as $e) { 
    $title = $e->nodeValue;
}

第一種方案中要使用iconv函數進行轉碼,第二種方案中不需要iconv轉碼,但需要在newDocumentFileHTML方法上提供“GBK字符集”。

還有一點很重要,在使用iconv函數轉碼是,一定要使用GBK,而不是使用gb2312,如果使用gb2312,iconv函數會很容易發生非法字符的報錯,使得轉碼失敗。

我以為有了這兩種方案護航后,亂碼問題再不會出現。可是,你要知道,做程序員很容易的心臟病的。當我把這些代碼部署到linux服務器上時,亂碼依舊。抓狂。

沒辦法,程序員的生活就是這樣。經過調試,發現,在linux服務器上,采用第二種方案的部分網頁仍然正常,但使用第一種方案時,需要去掉iconv函數轉碼。

下輩子一定不要做程序員。

來自:http://www.webhek.com/php-jquery/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!