一个错误我看到人们做了,并再次试图解析XML或HTML用正则表达式.以下是解析XML和HTML很难的几个原因:
人们希望将文件视为一系列行,但这是有效的:
<tag
attr="5"
/>
Run Code Online (Sandbox Code Playgroud)
人们希望将<或<tag视为标记的开头,但是这样的东西存在于野外:
<img src="imgtag.gif" alt="<img>" />
Run Code Online (Sandbox Code Playgroud)
人们通常希望将起始标记与结束标记匹配,但XML和HTML允许标记包含自身(传统的正则表达式根本无法处理):
<span id="outer"><span id="inner">foo</span></span>
Run Code Online (Sandbox Code Playgroud)
人们通常希望匹配文档的内容(例如着名的"查找给定页面上的所有电话号码"问题),但数据可能会被标记(即使在查看时看起来是正常的):
<span class="phonenum">(<span class="area code">703</span>)
<span class="prefix">348</span>-<span class="linenum">3020</span></span>
Run Code Online (Sandbox Code Playgroud)
评论可能包含格式不正确或不完整的标记:
<a href="foo">foo</a>
<!-- FIXME:
<a href="
-->
<a href="bar">bar</a>
Run Code Online (Sandbox Code Playgroud)
你还知道其他什么问题?
我每天都会看到问题,询问如何从某些HTML字符串中解析或提取某些内容,第一个答案/注释始终是"不要使用RegEx解析HTML,以免感到愤怒!" (有时省略最后一部分).
这对我来说相当混乱,我一直认为,解析任何复杂字符串的最佳方法是使用正则表达式.那么HTML解析器如何工作呢?它不使用正则表达式来解析.
使用正则表达式的一个特殊参数是,并不总是有一种解析替代方法(例如JavaScript,其中DOMDocument不是普遍可用的选项).例如,jQuery似乎可以使用正则表达式将HTML字符串转换为DOM节点.
不知道是否CW这个,这是一个真正的问题,我想要回答,而不是真正想成为一个讨论主题.
虽然regexp不是完全解析HTML文档的正确工具,但我发现很多人盲目地忽略了有关regexp的任何问题,如果他们在提议的文本中看到单个HTML标记那么多.
由于我们看到很多regexp的例子不是正确的工具,我对此提出了自己的看法:简单模式匹配比使用完整解析引擎更好的解决方案是什么?
我"试图"抓取页面中具有以下结构的网页:
<p class="row">
<span>stuff here</span>
<a href="http://www.host.tld/file.html">Descriptive Link Text</a>
<div>Link Description Here</div>
</p>
Run Code Online (Sandbox Code Playgroud)
我正在使用curl抓取网页:
<?php
$handle = curl_init();
curl_setopt($handle, CURLOPT_URL, "http://www.host.tld/");
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
$html = curl_exec($handle);
curl_close($handle);
?>
Run Code Online (Sandbox Code Playgroud)
我做了一些研究,发现我不应该使用正则表达式来解析从卷曲返回HTML,而且我应该使用PHP DOM.这就是我这样做的方式:
$newDom = new domDocument;
$newDom->loadHTML($html);
$newDom->preserveWhiteSpace = false;
$sections = $newDom->getElementsByTagName('p');
$nodeNo = $sections->length;
for($i=0; $i<$nodeNo; $i++){
$printString = $sections->item($i)->nodeValue;
echo $printString . "<br>";
}
Run Code Online (Sandbox Code Playgroud)
现在我并不假装我完全理解这一点,但我得到了要点,我确实得到了我想要的部分.唯一的问题是,我得到的只是HTML页面的文本,就像我从浏览器窗口中复制它一样.我想要的是实际的HTML,因为我想提取链接并使用它们,如下所示:
for($i=0; $i<$nodeNo; $i++){
$printString = $sections->item($i)->nodeValue;
echo "<a href=\"<extracted link>\">LINK</a> " . $printString . "<br>";
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我无法获得链接,因为我只获取网页的文本而不是我想要的来源.我知道"curl_exec"正在拉HTML,因为我已经尝试过了,所以我相信DOM在某种程度上剥离了我想要的HTML.