在PHP中如何从一个字符串中提取标题标签?

问题描述 投票:5回答:7

从一个包含大量 HTML 的字符串中,如何从 <h1><h2>etc 标签到一个新的变量中?

我想从这些元素中获取所有的文本,并将它们作为逗号分隔的值存储在一个新的变量中。

是否可以使用 preg_match_all()?

php text-extraction domparser
7个回答
2
投票

如果你真的想使用正则表达式,我认为,只要你的头标签没有嵌套,那么使用:

preg_match_all('/<h[0-6]>([^</h[0-6]>*)</h/i', $string, $matches);

只要你的头标签没有嵌套,正则表达式就可以用。正如其他人所说,如果你不控制HTML,正则表达式并不是一个很好的方法。


6
投票

首先你需要用tidy清理HTML(例子中的$html_str)。

$tidy_config = array(
    "indent"               => true,
    "output-xml"           => true,
    "output-xhtml"         => false,
    "drop-empty-paras"     => false,
    "hide-comments"        => true,
    "numeric-entities"     => true,
    "doctype"              => "omit",
    "char-encoding"        => "utf8",
    "repeated-attributes"  => "keep-last"
);

$xml_str = tidy_repair_string($html_str, $tidy_config);

然后你可以将XML($xml_str)加载到DOMDocument中。

$doc = DOMDocument::loadXML($xml_str);

最后你可以使用Horia Dragomir的方法:

$list = $doc->getElementsByTagName("h1");
for ($i = 0; $i < $list->length; $i++) {
    print($list->item($i)->nodeValue . "<br/>\n");
}

或者你也可以使用XPath对DOMDocument进行更复杂的查询(参见 http:/www.php.netmanualenclass.domxpath.php)

$xpath = new DOMXPath($doc);
$list = $xpath->evaluate("//h1");

3
投票

也请考虑本地 DOMDocument php类。

你可以使用 $domdoc->getElementsByTagName('h1') 来获取你的标题。


3
投票

我知道这是一个超级老的帖子,但是我想提一下我能够集体抓取标题标签的最好方法。

<h1>title</h1> and <h2>title 2</h2>

这个方法(就像regex一样,但是PHP的行为有点不同。)

/<\s*h[1-2](?:.*)>(.*)</\s*h/i

在你的 preg_match 中使用这个方法

|<\s*h[1-2](?:.*)>(.*)</\s*h|Ui

$group[1] 将包括标题标签之间的内容。 $group[0] 就是一切 <h1>test</h

这样就可以计算出空格,如果有人加上 "classid"

<h1 class="classname">test</h1>

classid(组)被忽略。

注释: 当我分析HTML标签时,我总是把所有的白色空格、换行符、制表符等剥离出来,用1个空格代替。这样可以减少多行、小数点......。以及大量的白色空间,这在某些情况下会扰乱regex格式。

  • 当然我只是抓取1-2个标题标签,改成0-9就可以全部抓取。
  • 如果还有人对我的代码有什么修改补充或者修复的地方,请回复,我真的很想知道。
  • 相反与Regex不好用HTML,这是一个很开放的说法。因为如果你设计你的php函数,以及regex表达式,完美地去除垃圾,并为regex特定表达式准备html,你将完全能够抓住你要找的东西。你可以做出足够多的regex函数来代替业余的html工作。

以下是测试页面的链接 检验


2
投票

建议不要在这项工作中使用regex,而是使用一些 SimpleHTMLDOM解析器


2
投票

你可能最好使用HTML解析器。但对于真正简单的场景,像这样的东西可能就可以了。

if (preg_match_all('/<h\d>([^<]*)<\/h\d>/iU', $str, $matches)) {
    // $matches contains all instances of h1-h6
}

0
投票

我只是想分享一下我的解决方案

function get_all_headings( $content ) {
    preg_match_all( '/\<(h[1-6])\>(.*)<\/h[1-6]>/i', $content, $matches );

    $r = array();
    if( !empty( $matches[1] ) && !empty( $matches[2] ) ){
        $tags = $matches[1];
        $titles = $matches[2];
        foreach ($tags as $i => $tag) {
            $r[] = array( 'tag' => $tag, 'title' => $titles[ $i ] );
        }
    }

    return $r;
}

如果没有找到标题,这个函数会返回一个空数组,或者类似这样。

array (
    array (
        'tag' => 'h1',
        'title' => 'This is a title',
    ),
    array (
        'tag' => 'h2',
        'title' => 'This is the second title',
    ),
)
© www.soinside.com 2019 - 2024. All rights reserved.