如何解析HTML/XML并从中提取信息?


当前回答

尝试简单HTML DOM解析器。

一个用PHP5+编写的HTMLDOM解析器,可以让您以非常简单的方式操作HTML!需要PHP 5+。支持无效的HTML。使用类似jQuery的选择器在HTML页面上查找标记。从HTML中提取单行内容。下载

注意:顾名思义,它可以用于简单的任务。它使用正则表达式而不是HTML解析器,因此对于更复杂的任务,速度会慢得多。它的大部分代码库是在2008年编写的,此后只做了一些小的改进。它不遵循现代PHP编码标准,将其纳入符合PSR的现代项目将是一个挑战。

示例:

如何获取HTML元素:

// Create DOM from URL or file
$html = file_get_html('http://www.example.com/');

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

// Find all links
foreach($html->find('a') as $element)
       echo $element->href . '<br>';

如何修改HTML元素:

// Create DOM from string
$html = str_get_html('<div id="hello">Hello</div><div id="world">World</div>');

$html->find('div', 1)->class = 'bar';

$html->find('div[id=hello]', 0)->innertext = 'foo';

echo $html;

从HTML中提取内容:

// Dump contents (without tags) from HTML
echo file_get_html('http://www.google.com/')->plaintext;

刮削Slashdot:

// Create DOM from URL
$html = file_get_html('http://slashdot.org/');

// Find all article blocks
foreach($html->find('div.article') as $article) {
    $item['title']     = $article->find('div.title', 0)->plaintext;
    $item['intro']    = $article->find('div.intro', 0)->plaintext;
    $item['details'] = $article->find('div.details', 0)->plaintext;
    $articles[] = $item;
}

print_r($articles);

其他回答

注意,这个答案推荐了那些已经废弃了10多年的图书馆。

phpQuery和QueryPath在复制流畅的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");
 }

大多数情况下,您希望为->find()使用简单的#id和.class或DIV标记选择器。但您也可以使用XPath语句,这有时会更快。另外,典型的jQuery方法,如->children()和->text(),特别是->attr(),简化了提取正确的HTML片段。(并且已经解码了它们的SGML实体。)

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

QueryPath还允许将新标记注入流(->追加),然后输出并美化更新的文档(->写入HTML)。它不仅可以解析格式错误的HTML,还可以解析各种XML方言(带有名称空间),甚至可以从HTML微格式(XFN、vCard)中提取数据。

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

.

phpQuery还是QueryPath?

一般来说,QueryPath更适合处理文档。而phpQuery还实现了一些伪AJAX方法(仅HTTP请求),以更接近于jQuery。据称,phpQuery通常比QueryPath更快(因为总体特性较少)。

有关差异的更多信息,请参阅tagbyte.org上的wayback机器上的比较

优势

简单可靠易于使用的替代方案->查找(“a img,a object,div a”)正确的数据取消捕获(与正则表达式grepping相比)

对于1a和2:我将投票支持新的Symfony Componet类DOMCrawler(DOMCrawler)。此类允许类似于CSS选择器的查询。看看这个演示文稿,看看真实世界的例子:news-of-the-symfony2-world。

该组件设计为独立工作,可以在没有Symfony的情况下使用。

唯一的缺点是它只适用于PHP5.3或更高版本。

不使用正则表达式解析HTML有几个原因。但是,如果您完全控制将生成什么HTML,那么可以使用简单的正则表达式。

上面是一个通过正则表达式解析HTML的函数。请注意,此函数非常敏感,要求HTML遵守某些规则,但它在许多场景中都非常有效。如果您想要一个简单的解析器,并且不想安装库,请尝试一下:

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产生影响。

是的,您可以使用simple_html_dom。然而,我已经使用simple_html_dom做了很多工作,特别是在web抓取方面,发现它太脆弱了。它做了基本的工作,但无论如何我都不推荐它。

我从未使用过卷发,但我学到的是,卷发可以更有效地完成这项工作,而且更结实。

请查看此链接:使用curl刮取网站