如何确定html标签是否分成多行

时间:2008-08-29 02:03:39

标签: php html scripting

我正在编写一个涉及抓取网页的PHP脚本。目前,该脚本逐行分析页面,但如果有一个跨越多行的标记,它就会中断,例如

<img src="example.jpg"
alt="example">

如果情况变得更糟,我可以通过删除所有换行符来预处理页面,然后将它们重新插入到最近的>,但这看起来像是一个kludge。

理想情况下,我能够检测到跨越线条的标记,仅与线条相连,并继续处理。
那么检测这个的最佳方法是什么?

6 个答案:

答案 0 :(得分:7)

这是我的一个烦恼:从不手工解析HTML。 从不使用regexp解析HTML。 从不使用字符串比较解析HTML。 始终使用HTML解析器来解析HTML - 这就是他们的目的。

自从我完成任何PHP以来已经很长时间了,但是快速搜索了this PHP5 HTML parser

答案 1 :(得分:2)

不要写一个解析器,使用别人的:DOMDocument::loadHTML - 这只是一个,我认为还有很多其他的。

答案 2 :(得分:1)

嗯,这不是回答问题而是更多的意见,但是......

我认为最好的抓取策略(因此,消除这个问题)不是逐行分析HTML,这对HTML来说是不自然的,而是通过它的自然分隔符来分析它:&lt;&gt;对

课程有两种类型:

  • 立即关闭的标签元素,例如&lt; br /&gt;
  • 标记需要单独结束标记的元素,例如&lt; p>文字&lt; / p&gt;

对于段落(p)标记,您可以立即看到使用此策略的优势:解析多行段落更容易,而不必跟踪结束标记的位置。

答案 3 :(得分:1)

也许对于未来的项目,我会使用解析库,但除了手头的问题之外,这有点不对劲。这是我目前的解决方案。 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);
    }
}

这可能会以某种方式进行优化,但就我的目的而言,这已经足够了。

答案 4 :(得分:0)

为什么不在一行中读取,并将其设置为字符串,然后检查字符串是否有标记打开和关闭,如果标记跨越多行,则将下一行添加到字符串中并移动部分之前打开支撑到您处理过的字符串。然后只需解析整个文件就可以了。它不漂亮,但它应该工作。

答案 5 :(得分:0)

如果您必须坚持使用当前的解析方法,并且它是正则表达式,则可以使用multi-line flag“m”跨越多行。