如何解析部分 HTML?
Posted
技术标签:
【中文标题】如何解析部分 HTML?【英文标题】:How do I parse partial HTML? 【发布时间】:2010-12-28 08:45:26 【问题描述】:我正在尝试在 php 中使用 DOM 解析一些 html,但遇到了一些问题。首先,如果这改变了解决方案,我拥有的 HTML 不是一个完整的页面,而是它的一部分。
<!-- This is the HTML that I have --><a href='/games/'>
<div id='game'>
<img src='http://images.example.com/games.gif' width='300' height='137' border='0'>
<br><b> Game </b>
</div>
<div id='double'>
<img src='http://images.example.com/double.gif' width='300' height='27' border='0' alt='' title=''>
</div>
</a>
现在我试图只获取 ID 为 double
的 div。我已经尝试了以下代码,但它似乎无法正常工作。我可能做错了什么?
//The HTML has been loaded into the variable $html
$dom=new domDocument;
$dom->loadHTML($html);
$dom->preserveWhiteSpace = false;
$keepme = $dom->getElementById('double');
$contents = '<div style="text-align:center">'.$keepme.'</a></div>';
echo $contents;
【问题讨论】:
它在做什么或不做什么? 【参考方案1】:HTML Tidy 应该能够“纠正”破碎和碎片化的 HTML 文档,将它们变成可以用其他工具解析的东西
http://devzone.zend.com/article/761
Tidy 扩展是 PHP 5 中的新功能, 并且可以从 PHP 版本获得 5.0b3 向上。它基于 TidyLib 库,并允许 开发人员进行验证、修复和 解析 HTML、XHTML 和 XML 文档 来自 PHP。
【讨论】:
【参考方案2】:来自DomDocument::getElementById
要使此功能起作用,您将 需要要么设置一些ID属性 使用 DOMElement::setIdAttribute 或 DTD 将属性定义为 类型 ID。在后一种情况下,您 需要验证您的文件 使用 DOMDocument::validate 或 DOMDocument->validateOnParse 之前 使用这个函数。
更多信息
Simplify PHP DOM XML parsing - how? How do you parse and process HTML/XML in PHP?由于迟早有人会提到使用正则表达式来做这件事,所以您可以使用以下模式:/<div id='double'>(.*)<\/div>/simU
此外,您可以只使用常规字符串函数来提取 div 部分,例如
$div = strstr($html, '<div id="double">');
$div = substr($div, 0, strpos($div, '</div>') + 6);
echo $div;
虽然我同意,你不应该使用 RegEx 或 String 函数来解析 HTML 或 XML,我觉得这样做绝对没问题,只要你唯一关心的是得到这个片段中的单个 div。保持简单。
【讨论】:
当然,除非有嵌套的 div 标签。正则表达式不是用于解析html。 如果他真的在解析那个片段,我会同意。但他只是想从中提取一个明确定义的片段。又不是他在遍历DOM,所以我想把fragment当作字符串来处理就可以了。 此外,我在第一句话中已经将他指向 SimpleHTML。【参考方案3】:我认为DOMDocument::getElementById
不适用于您的情况:(引用)
要使此功能起作用,您将 需要设置一些ID属性 与
DOMElement::setIdAttribute
或 DTD 将属性定义为 类型 ID。 在后一种情况下,您 需要验证您的文件 与DOMDocument::validate
或DOMDocument->validateOnParse
之前 使用这个函数。
一个可能有效的解决方案是使用一些 XPath query 来提取您正在寻找的元素。
首先,让我们加载 HTML 部分,就像你第一次做的那样:
$dom=new domDocument;
$dom->loadHTML($html);
var_dump($dom->saveHTML());
var_dump
在这里只是为了证明 HTML 部分已经成功加载——从它的输出来看,它已经成功了。
然后,实例化DOMXPath
类,并使用它来查询您想要获取的元素:
$xpath = new DOMXpath($dom);
$result = $xpath->query("//*[@id = 'double']");
$keepme = $result->item(0);
我们现在必须添加你想要的元素 ;-)
但是,为了将它的 HTML 内容注入到另一个 HTML 段中,我们必须首先获取它的 HTML 内容。
我不记得有任何“简单”的方法可以做到这一点,但是像这样的东西可以解决问题:
$tempDom = new DOMDocument();
$tempImported = $tempDom->importNode($keepme, true);
$tempDom->appendChild($tempImported);
$newHtml = $tempDom->saveHTML();
var_dump($newHtml);
而且...我们有您的double
<div>
的 HTML 内容:
string '<div id="double">
<img src="http://images.example.com/double.gif" border="0" title="">
</div>
' (length=125)
现在,你只需要用它做任何你想做的事;-)
【讨论】:
是的!我到处寻找如何获取片段与完整的 HTML 文档,几乎放弃了。谢谢!【参考方案4】:一个 XML 文档在根级别只能有一个元素。很可能,HTML 解析器也有类似的要求。尝试将内容包装在 <body/>
标记中。
似乎是别的东西。 This page 描述了可能的原因。我建议您使用 XPath 来获取元素。
【讨论】:
【参考方案5】:片段是 HTML,但要通过 DOM 解析,它应该是 XHTML。 每个打开的标签都必须关闭。
在您的情况下,这意味着您应该将 <br>
替换为 <br />
并将 <img ... >
替换为 <img ... />
【讨论】:
这实际上不是真的。 $dom->loadHTML("") 工作得很好并且不会失败解析。事实上,$dom->saveXML() 会显示带有正确闭合标签的输出。 这完全取决于您使用的库。在 python 中: xml.dom.minidom.parseString("") -> 返回异常。 xml.dom.minidom.parseString("") 有效。我宁愿一开始就以正确的格式输入,而不是像我期望的那样依赖库来解析不正确的输入。【参考方案6】:在同一个问题苦苦挣扎了几个小时后,我找到了这个对我有用的解决方案,与我在网上找到的其他解决方案相比,它相对简单。
此解决方案修复了不需要的 DOCTYPE 和 html、正文标签以及编码问题。
$htmlContent = "<h1>This is a heading</h1><p>This is a paragraph</p>";
// 1.) Load the html
$dom = new DOMDocument();
$dom->loadHTML("<meta http-equiv='Content-Type' content='charset=utf-8' /><div>$htmlContent</div>");
// 2.) Do you logic
$dom->getElementsByTagName('h1')[0]->setAttribute('class', 'happy');
// 3.) Render the html
$wrapperNode = $dom->getElementsByTagName('div')[0];
$renderedHtml = $dom->saveHTML($wrapperNode);
// If you want to keep the wrapper div
echo $renderedHtml;
// Or remove the wrapper <div>
echo substr(trim($renderedHtml), 5, -6);
【讨论】:
以上是关于如何解析部分 HTML?的主要内容,如果未能解决你的问题,请参考以下文章
如何解决 Django 中显示“无法解析剩余部分”的 TemplateSyntaxError