题
我正在编写一个涉及抓取网页的 PHP 脚本。目前,该脚本逐行分析页面,但如果存在跨多行的标签,则会中断,例如
<img src="example.jpg"
alt="example">
如果情况更糟,我可以通过删除所有换行符来预处理页面,然后在最近的位置重新插入它们 >
, ,但这似乎是一个拼凑。
理想情况下,我能够检测到跨行的标签,仅将这些标签连接到行,然后继续处理。
那么检测这一点的最佳方法是什么?
解决方案 4
也许对于未来的项目,我将使用解析库,但这与当前的问题无关。这是我目前的解决方案。 rstrpos
是 strpos,但方向相反。使用示例:
for($i=0; $i<count($lines); $i++)
{
$line = handle_mulitline_tags(&$i, $line, $lines);
}
这是该实现:
function rstrpos($string, $charToFind, $relativePos)
{
$searchPos = $relativePos;
$searchChar = '';
while (($searchChar != $charToFind)&&($searchPos>-1))
{
$newPos = $searchPos-1;
$searchChar = substr($string,$newPos,strlen($charToFind));
$searchPos = $newPos;
}
if (!empty($searchChar))
{
return $searchPos;
return TRUE;
}
else
{
return FALSE;
}
}
function handle_multiline_tags(&$i, $line, $lines)
{
//if a tag is opened but not closed before a line break,
$open = rstrpos($line, '<', strlen($line));
$close = rstrpos($line, '>', strlen($line));
if(($open > $close)&&($open > -1)&&($close > -1))
{
$i++;
return trim($line).trim(handle_multiline_tags(&$i, $lines[$i], $lines));
}
else
{
return trim($line);
}
}
这可能可以以某种方式进行优化,但对于我的目的来说,这已经足够了。
其他提示
这是我最讨厌的事情之一: 绝不 手动解析 HTML。 绝不 使用正则表达式解析 HTML。 绝不 通过字符串比较来解析 HTML。 总是 使用 HTML 解析器来解析 HTML – 这就是它们的用途。
已经很久没有写PHP了,但是快速搜索一下就发现了 这个 PHP5 HTML 解析器.
不要编写解析器,使用别人的: DOMDocument::loadHTML ——这只是其中之一,我想还有很多其他的。
好吧,这并没有回答问题,更多的是一种意见,但是......
我认为最好的抓取策略(从而消除这个问题)不是逐行分析 HTML,这对于 HTML 来说是不自然的,而是通过其自然分隔符来分析它:<> 对。
当然会有两种类型:
- 立即关闭的标签元素,例如 < br />
- 需要单独结束标记的标记元素,例如 < p > text </p >
您可以立即看到在段落(p)标签的情况下使用此策略的优势:解析多行段落会更容易,而不必跟踪结束标记的位置。
为什么不读取一行,并将其设置为一个字符串,然后检查字符串中的标签开头和结尾,如果标签跨越多于一行,则将下一行添加到字符串中,并将该部分移动到左大括号之前到您处理过的字符串。然后只需解析整个文件即可。它不漂亮,但应该有用。
如果您必须坚持当前的解析方法,并且它是正则表达式,则可以使用 多行标志 “m”跨越多行。