我正在编写一个涉及抓取网页的 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”跨越多行。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top