php - xml教學 - xml parser online




你如何在PHP中解析和處理HTML/XML? (19)

原生XML擴展

我更喜歡使用其中一個原生XML擴展,因為它們與PHP捆綁在一起,通常比所有第三方庫更快,並且在標記上給我所需的所有控制權。

DOM

DOM擴展允許您通過PHP API使用PHP 5對XML文檔進行操作。它是W3C的文檔對像模型核心級別3的實現,這是一個平台和語言中立的接口,允許程序和腳本動態訪問和更新文件的內容,結構和風格。

DOM能夠解析和修改現實世界(破碎)的HTML,並且可以執行XPath查詢 。 它基於libxml

使用DOM需要一些時間才能提高效率,但這個時間非常值得IMO。 由於DOM是一個與語言無關的接口,因此您可以找到多種語言的實現,因此如果您需要更改編程語言,那麼您很可能已經知道如何使用該語言的DOM API。

一個基本的用法示例可以在抓取A元素的href屬性中找到,一般的概念概述可以在php的DOMDocument中找到

StackOverflow上已經廣泛介紹瞭如何使用DOM擴展 ,因此如果您選擇使用它,您可以確定您遇到的大多數問題都可以通過搜索/瀏覽Stack Overflow來解決。

XMLReader

XMLReader擴展是一個XML pull解析器。 讀取器在文檔流上作為光標前進,並在途中停在每個節點上。

與DOM一樣,XMLReader基於libxml。 我不知道如何觸發HTML Parser模塊,因此使用XMLReader解析損壞的HTML的可能性可能不如使用DOM,因為您可以明確告訴它使用libxml的HTML Parser Module。

使用php從h1標籤獲取所有值時,可以找到一個基本用法示例

XML解析器

此擴展允許您創建XML解析器,然後為不同的XML事件定義處理程序。 每個XML解析器還有一些您可以調整的參數。

XML Parser庫也基於libxml,並實現了SAX樣式的XML推送解析器。 它可能是比DOM或SimpleXML更好的內存管理選擇,但是比XMLReader實現的pull解析器更難以使用。

SimpleXml

SimpleXML擴展提供了一個非常簡單且易於使用的工具集,用於將XML轉換為可以使用普通屬性選擇器和數組迭代器處理的對象。

當您知道HTML是有效的XHTML時,SimpleXML是一個選項。 如果你需要解析破碎的HTML,甚至不要考慮SimpleXml,因為它會窒息。

一個基本的用法示例可以在一個簡單的程序到CRUD節點和xml文件的節點值 中找到,PHP手冊中還有很多其他的例子

第三方庫(基於libxml)

如果您更喜歡使用第三方庫,我建議使用實際上使用DOM / libxml而不是字符串解析的庫。

FluentDom

FluentDOM為PHP中的DOMDocument提供了類似jQuery的流暢XML接口。 選擇器是用XPath或CSS編寫的(使用CSS到XPath轉換器)。 當前版本擴展了DOM實現標準接口並添加了DOM Living Standard的功能。 FluentDOM可以加載JSON,CSV,JsonML,RabbitFish等格式。 可以通過Composer安裝。

HtmlPageDom

Wa72 \ HtmlPageDom`是一個用於輕鬆操作HTML文檔的PHP庫。它需要來自Symfony2組件的DomCrawler來遍歷DOM樹,並通過添加操作HTML文檔的DOM樹的方法來擴展它。

phpQuery (多年未更新)

phpQuery是一個服務器端,可鏈接,CSS3選擇器驅動的文檔對像模型(DOM)API,基於用PHP5編寫的jQuery JavaScript庫,並提供額外的命令行界面(CLI)。

另見: https://github.com/electrolinux/phpqueryhttps://github.com/electrolinux/phpquery

Zend_Dom

Zend_Dom提供了處理DOM文檔和結構的工具。 目前,我們提供Zend_Dom_Query,它提供了一個統一的界面,用於使用XPath和CSS選擇器查詢DOM文檔。

QueryPath

QueryPath是一個用於操作XML和HTML的PHP​​庫。 它不僅適用於本地文件,還適用於Web服務和數據庫資源。 它實現了大部分jQuery接口(包括CSS樣式選擇器),但它經過大量調整以供服務器端使用。 可以通過Composer安裝。

fDOMDocument

fDOMDocument擴展了標準DOM,以便在所有錯誤情況下使用異常,而不是PHP警告或通知。 為方便起見,他們還添加了各種自定義方法和快捷方式,並簡化了DOM的使用。

sabre/xml

saber / xml是一個包裝和擴展XMLReader和XMLWriter類的庫,用於創建一個簡單的“xml到對象/數組”映射系統和設計模式。 編寫和讀取XML是單遍的,因此可以快速並且需要大型xml文件的低內存。

FluidXML

FluidXML是一個PHP庫,用於通過簡潔流暢的API來操作XML。 它利用XPath和流暢的編程模式,既有趣又有效。

第三方(不是基於libxml的)

構建DOM / libxml的好處是,您可以獲得良好的開箱即用性能,因為您基於本機擴展。 但是,並非所有第三方庫都沿著這條路線行進。 其中一些列在下面

PHP簡單的HTML DOM解析器

  • 用PHP5 +編寫的HTML DOM解析器允許您以非常簡單的方式操作HTML!
  • 需要PHP 5+。
  • 支持無效的HTML。
  • 使用選擇器在HTML頁面上查找標籤,就像jQuery一樣。
  • 從一行中提取HTML中的內容。

我一般不推薦這個解析器。 代碼庫很糟糕,解析器本身很慢而且內存很耗。 並非所有jQuery選擇器(例如子選擇器 )都是可能的。 任何基於libxml的庫都應該比這更容易。

PHP Html解析器

PHPHtmlParser是一個簡單,靈活的html解析器,允許您使用任何css選擇器(如jQuery)選擇標籤。 目標是協助開發需要快速,簡單的方法來廢棄html的工具,無論它是否有效! 這個項目是由sunra / php-simple-html-dom-parser原創支持的,但支持似乎已經停止,所以這個項目是我對他以前工作的改編。

同樣,我不推薦這個解析器。 CPU使用率很高,速度相當慢。 還沒有清除已創建DOM對象的內存的功能。 這些問題尤其適用於嵌套循環。 文檔本身不准確且拼寫錯誤,自4月14日以來沒有對修復的響應。

Ganon

  • 通用標記器和HTML / XML / RSS DOM解析器
    • 能夠操縱元素及其屬性
    • 支持無效的HTML和UTF8
  • 可以對元素執行類似CSS3的高級查詢(比如jQuery - 支持的命名空間)
  • HTML美化器(如HTML Tidy)
    • 縮小CSS和Javascript
    • 排序屬性,更改字符大小寫,更正縮進等。
  • 擴展
    • 使用基於當前字符/標記的回調解析文檔
    • 操作以較小的功能分隔,以便輕鬆覆蓋
  • 快速而簡單

從未使用過它。 不知道它是否有用。

HTML 5

您可以使用上面的方法來解析HTML5,但由於HTML5允許的標記,可能存在怪癖 。 因此,對於HTML5,您要考慮使用專用解析器,例如

html5lib

基於WHATWG HTML5規範的HTML解析器的Python和PHP實現,可最大程度地兼容主要桌面Web瀏覽器。

HTML5最終確定後,我們可能會看到更多專用解析器。 還有一個W3的博客文章,名為How-To for html 5 parsing ,值得一試。

網頁服務

如果您不想編寫PHP,也可以使用Web服務。 一般來說,我發現這些實用程序的效用很小,但這只是我和我的用例。

YQL

YQL Web服務使應用程序能夠在Internet上查詢,過濾和組合來自不同來源的數據。 YQL語句具有類似SQL的語法,對於具有數據庫經驗的任何開發人員來說都很熟悉。

ScraperWiki

ScraperWiki的外部界面允許您以您希望在Web或您自己的應用程序中使用的形式提取數據。 您還可以提取有關任何刮刀狀態的信息。

常用表達

最後也是最不推薦的 ,您可以使用正則表達式從HTML中提取數據。 通常,不鼓勵在HTML上使用正則表達式。

您在網上找到的大多數與標記相匹配的片段都很脆弱。 在大多數情況下,它們只適用於非常特殊的HTML。 微小的標記更改,例如在某處添加空格,或添加或更改標記中的屬性,可能會導致RegEx在未正確編寫時失敗。 在HTML上使用RegEx之前,您應該知道自己在做什麼。

HTML解析器已經知道HTML的語法規則。 必須為您編寫的每個新RegEx講授正則表達式。 RegEx在某些情況下很好,但它實際上取決於您的用例。

可以編寫更可靠的解析器 ,但是使用正則表達式編寫完整可靠的自定義解析器是浪費時間,因為上述庫已經存在並且在此方面做得更好。

另見Parsing Html The Cthulhu Way

圖書

如果你想花一些錢,看看吧

我不隸屬於PHP Architect或作者。

如何解析HTML / XML並從中提取信息?


phpQueryQueryPath在復制流暢的jQuery API方面非常相似。 這也是為什麼它們是在PHP中正確解析HTML的兩種最簡單的方法。

QueryPath的示例

基本上,您首先從HTML字符串創建可查詢的DOM樹:

 $qp = qp("<html><body><h1>title</h1>..."); // or give filename or URL

生成的對象包含HTML文檔的完整樹表示。 它可以使用DOM方法遍歷。 但常見的方法是使用jQuery中的CSS選擇器:

 $qp->find("div.classname")->children()->...;

 foreach ($qp->find("p img") as $img) {
     print qp($img)->attr("src");
 }

大多數情況下,您希望使用簡單的#id.classDIV標籤選擇器->find() 。 但您也可以使用XPath語句,有時速度更快。 另外,典型的jQuery方法,如->children()->text() ,特別是->attr()簡化提取正確的HTML代碼段。 (已經解碼了他們的SGML實體。)

 $qp->xpath("//div/p[1]");  // get first paragraph in a div

QueryPath還允許將新標記註入流( ->append ),然後輸出並美化更新的文檔( ->writeHTML )。 它不僅可以解析格式錯誤的HTML,還可以解析各種XML方言(帶名稱空間),甚至可以從HTML微格式(XFN,vCard)中提取數據。

 $qp->find("a[target=_blank]")->toggleClass("usability-blunder");

phpQuery還是QueryPath?

通常,QueryPath更適合處理文檔。 雖然phpQuery也實現了一些偽AJAX方法(只是HTTP請求),更接近jQuery。 據說phpQuery通常比QueryPath更快(因為整體功能較少)。

有關差異的更多信息,請參閱tagbyte.org上的返回機器上的這種比較 。 (原始來源丟失了,所以這裡是一個互聯網檔案鏈接。是的,你仍然可以找到丟失的頁面,人。)

這是一個全面的QueryPath介紹

優點

  • 簡單性和可靠性
  • 簡單易用的替代方法->find("a img, a object, div a")
  • 正確的數據轉義(與正則表達式grepping相比)

Advanced Html Dom是一個簡單的HTML DOM替換,提供相同的接口,但它基於DOM,這意味著不會發生任何相關的內存問題。

它還具有完整的CSS支持,包括jQuery擴展。


QueryPath很好,但是如果你沒有意識到它意味著什麼就要小心“跟踪狀態”,這可能意味著你浪費了大量的調試時間來試圖找出發生了什麼以及為什麼代碼不起作用。

這意味著結果集上的每個調用都會修改對像中的結果集,它不像jquery中那樣可鏈接,其中每個鏈接都是一個新集合,你有一個集合,它是查詢的結果,每個函數調用都會修改那一套。

為了獲得類似jquery的行為,你需要在進行過濾/修改之類的操作之前進行分支,這意味著它將更加密切地反映jquery中發生的事情。

$results = qp("div p");
$forename = $results->find("input[name='forename']");

$results現在包含input[name='forename']的結果集而不是原始查詢"div p"這讓我大吃一驚 ,我發現QueryPath跟踪過濾器並查找修改結果和存儲的所有內容他們在對像中。 你需要這樣做

$forename = $results->branch()->find("input[name='forname']")

那麼$results將不會被修改,你可以一次又一次地重複使用結果集,也許有更多知識的人可以清楚一點,但它基本上就像我發現的那樣。


I've created a library called HTML5DOMDocument that is freely available at https://github.com/ivopetkov/html5-dom-document-php

它也支持查詢選擇器,我認為在您的情況下將非常有用。 這是一些示例代碼:

$dom = new IvoPetkov\HTML5DOMDocument();
$dom->loadHTML('<!DOCTYPE html><html><body><h1>Hello</h1><div class="content">This is some text</div></body></html>');
echo $dom->querySelector('h1')->innerHTML;

JSON and array from XML in three lines:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

Ta da!


There are many ways to process HTML/XML DOM of which most have already been mentioned. Hence, I won't make any attempt to list those myself.

I merely want to add that I personally prefer using the DOM extension and why :

  • iit makes optimal use of the performance advantage of the underlying C code
  • it's OO PHP (and allows me to subclass it)
  • it's rather low level (which allows me to use it as a non-bloated foundation for more advanced behavior)
  • it provides access to every part of the DOM (unlike eg. SimpleXml, which ignores some of the lesser known XML features)
  • it has a syntax used for DOM crawling that's similar to the syntax used in native Javascript.

And while I miss the ability to use CSS selectors for DOMDocument , there is a rather simple and convenient way to add this feature: subclassing the DOMDocument and adding JS-like querySelectorAll and querySelector methods to your subclass.

For parsing the selectors, I recommend using the very minimalistic CssSelector component from the Symfony framework . This component just translates CSS selectors to XPath selectors, which can then be fed into a DOMXpath to retrieve the corresponding Nodelist.

You can then use this (still very low level) subclass as a foundation for more high level classes, intended to eg. parse very specific types of XML or add more jQuery-like behavior.

The code below comes straight out my PHPPowertools/DOM-Query and uses the technique I described.

For HTML parsing :

namespace PowerTools;

use \Symfony\Component\CssSelector\CssSelector as CssSelector;

class DOM_Document extends \DOMDocument {
    public function __construct($data = false, $doctype = 'html', $encoding = 'UTF-8', $version = '1.0') {
        parent::__construct($version, $encoding);
        if ($doctype && $doctype === 'html') {
            @$this->loadHTML($data);
        } else {
            @$this->loadXML($data);
        }
    }

    public function querySelectorAll($selector, $contextnode = null) {
        if (isset($this->doctype->name) && $this->doctype->name == 'html') {
            CssSelector::enableHtmlExtension();
        } else {
            CssSelector::disableHtmlExtension();
        }
        $xpath = new \DOMXpath($this);
        return $xpath->query(CssSelector::toXPath($selector, 'descendant::'), $contextnode);
    }

    [...]

    public function loadHTMLFile($filename, $options = 0) {
        $this->loadHTML(file_get_contents($filename), $options);
    }

    public function loadHTML($source, $options = 0) {
        if ($source && $source != '') {
            $data = trim($source);
            $html5 = new HTML5(array('targetDocument' => $this, 'disableHtmlNsInDom' => true));
            $data_start = mb_substr($data, 0, 10);
            if (strpos($data_start, '<!DOCTYPE ') === 0 || strpos($data_start, '<html>') === 0) {
                $html5->loadHTML($data);
            } else {
                @$this->loadHTML('<!DOCTYPE html><html><head><meta charset="' . $encoding . '" /></head><body></body></html>');
                $t = $html5->loadHTMLFragment($data);
                $docbody = $this->getElementsByTagName('body')->item(0);
                while ($t->hasChildNodes()) {
                    $docbody->appendChild($t->firstChild);
                }
            }
        }
    }

    [...]
}

See also Parsing XML documents with CSS selectors by Symfony's creator Fabien Potencier on his decision to create the CssSelector component for Symfony and how to use it.


There are several reasons to not parse HTML by regular expression. But, if you have total control of what HTML will be generated, then you can do with simple regular expression.

Above it's a function that parses HTML by regular expression. Note that this function is very sensitive and demands that the HTML obey certain rules, but it works very well in many scenarios. If you want a simple parser, and don't want to install libraries, give this a shot:

function array_combine_($keys, $values) {
    $result = array();
    foreach ($keys as $i => $k) {
        $result[$k][] = $values[$i];
    }
    array_walk($result, create_function('&$v', '$v = (count($v) == 1)? array_pop($v): $v;'));

    return $result;
}

function extract_data($str) {
    return (is_array($str))
        ? array_map('extract_data', $str)
        : ((!preg_match_all('#<([A-Za-z0-9_]*)[^>]*>(.*?)</\1>#s', $str, $matches))
            ? $str
            : array_map(('extract_data'), array_combine_($matches[1], $matches[2])));
}

print_r(extract_data(file_get_contents("http://www.google.com/")));


只需使用DOMDocument->loadHTML()並完成它。 libxml的HTML解析算法非常好而且速度快,而且與普遍看法相反,它不會阻礙格式錯誤的HTML。


對於1a和2:我會投票支持新的Symfony Componet類DOMCrawler( DomCrawler )。 此類允許類似於CSS選擇器的查詢。 看看這個演示文稿,了解真實世界的例子: news-of-the-symfony2-world

該組件設計為獨立工作,無需Symfony即可使用。

唯一的缺點是它只適用於PHP 5.3或更高版本。


對於HTML5 ,html5 lib已經被放棄多年了。 我能找到的唯一一個帶有最新更新和維護記錄的HTML5庫是html5-php ,它剛剛在一周之前被帶到beta 1.0。


您可以嘗試的另一個選項是QueryPath 。 It's inspired by jQuery, but on the server in PHP and used in Drupal .


我們之前已經為我們的需求創建了很多爬蟲。 在一天結束時,通常是簡單的正則表達式來做最好的事情。 雖然上面列出的庫是好的,但是如果你知道你在尋找什麼,正則表達式是一種更安全的方式,因為你也可以處理無效的HTML / XHTML結構,如果加載的話,它會失敗通過大多數解析器。


我在這裡沒有提到的一個通用方法是通過Tidy運行HTML,可以將其設置為吐出有保證的有效XHTML。 然後您可以在其上使用任何舊的XML庫。

但是對於你的具體問題,你應該看看這個項目: http://fivefilters.org/content-only/http://fivefilters.org/content-only/ - 它是Readability算法的修改版本,它被設計為只提取文本內容(不是標題)和一個頁腳。


我推薦PHP Simple HTML DOM Parser

它確實有很好的功能,例如:

foreach($html->find('img') as $element)
       echo $element->src . '<br>';

是的,你可以使用simple_html_dom來達到目的。 但是我在simple_html_dom上做了很多工作,特別是對於網頁報廢,並且發現它太脆弱了。 它完成了基本工作,但我不會推薦它。

我從來沒有使用捲曲,但我學到的是捲曲可以更有效地完成工作並且更加堅固。

請查看此鏈接: scraping-websites-with-curl


簡單的HTML DOM是一個很好的開源解析器:

simplehtmldom.sourceforge

它以面向對象的方式處理DOM元素,並且新的迭代對非兼容代碼有很多覆蓋。 還有一些很棒的函數,比如你在JavaScript中看到的,比如“find”函數,它將返回該標記名稱的所有元素實例。

我已經在許多工具中使用它,在許多不同類型的網頁上測試它,我認為它很有用。






html-parsing