我已经在Stack Overflow及其姐妹网站上大量阅读了这篇文章,我知道使用正则表达式解析HTML并不是最好的做法。我没有尝试进行任何严肃的解析或非常具体的解析,只需抓住几页中非常一致的几个重复元素。然后从这些元素中,我将执行其他网络抓取任务。
我的一般问题在于我试图抓住元素,包括开启和关闭元素。 (特别是在这种情况下,一组' li'元素)
<li id="result_0" data-asin="<8 char hash>"> ........ </li>
<li id="result_1" data-asin="<8 char hash>"> ........ </li>
<li id="result_2" data-asin="<8 char hash>"> ........ </li>
<li id="result_3" data-asin="<8 char hash>"> ........ </li>
<li id="result_4" data-asin="<8 char hash>"> ........ </li>
....
<li id="result_15" data-asin="<8 char hash>"> ........ </li>
<li id="result_16" data-asin="<8 char hash>"> ........ </li>
<li id="result_17" data-asin="<8 char hash>"> ........ </li>
...
我使用的代码是(PHP):
$pattern = '/[<][l][i]\s[i][d][=]["][a-z]{6}[_][0-9]{1,2}[^li]+/';
$matches = array();
$topics = array();
preg_match_all($pattern, $source, $matches);
var_dump($matches);
和$ matches返回
array (size=1)
0 =>
array (size=28)
0 => string '<li id="result_0" data-as' (length=25)
1 => string '<li id="result_1" data-as' (length=25)
2 => string '<li id="result_2" data-as' (length=25)
3 => string '<li id="result_3" data-as' (length=25)
......
......
我知道我会停留在&#39; i&#39;在data-asin因为[^ li]但是我不知道该如何说:接受换行符和除&#34;&lt; / li&gt;&#34;
之外的所有字符注意:在LI元素之间没有其他LI元素可以搞砸寻找结束LI元素
还有:
[<][l][i]\s[i][d][=]["]
开始我的模式看起来像垃圾。有没有办法将文字文本分组并搜索它? (例如:寻找 - &gt;&#34;&lt; li id =&#39;&#34;)我假设这将导致我搜索我的&#34;&lt; / li&gt;& #34;同样。
对于最后一次&lt; / li&gt;,如何搜索UNTIL&lt; / li&gt;所有内容?
答案 0 :(得分:2)
你真的非常更好地使用解析器和一些xpath查询,例如要获取所有列表项,您只需要两行:
$xml = simplexml_load_file($url);
$items = $xml->xpath("//li[starts-with(@id, 'result_')]");
foreach ($items as $item) {
// do sth. with the item
}
特别是当您的data-asin
属性包含<
和>
。
答案 1 :(得分:1)
我的前言是我不熟悉PHP,但正则表达式在各种语言中通常是相同或相似的。
简化模式:/<li id="result_\d+" data-asin=".{8}">[^<]+<\/li>/
如果您只想盲目地抓取所有li
代码,无论id
或data-asin
属性如何,都可以进一步简化。
答案 2 :(得分:1)
排序的正则表达式
<(li|ol|otherelement)[\s\S]+?<\/(\1)>
在第一个()中,你可以放置你想要你的正则表达式找到的所有元素,并且(\ 1)反向引用将确保匹配它们的结束标记。 [\ S \ S] +?基本上是所有人物,甚至新行,一个或多个? - 这使得它很难确保捕获该元素类型的第一个可能的结束标记。
答案 3 :(得分:1)
<li id="result_0" data-asin="<8 char hash>"> ........ </li>
~\Q<li id="\E([^"]*)\Q" data-asin="\E([a-zA-Z]{8})\Q">\E(.*)\Q</li>\E~
答案 4 :(得分:0)
更简单的模式
(?<=li id\=).*(?=\<\/li\>)
答案 5 :(得分:0)
我能给你的最好建议是阅读正则表达式教程,了解你的正则表达式方法有什么问题。否则为了获得你想要的东西,用正则表达式搜索纯文本的html并不是好方法。使用html结构:
$dom = new DOMDocument;
$dom->loadHTML($html);
$lis = $dom->getElementsByTagName('li');
foreach($lis as $li) {
if (preg_match('/^[a-z]{6}_[0-9]{1,2}$/', $li->getAttribute('id')))
echo $dom->saveHTML($li) . PHP_EOL;
}