2010-01-14 121 views

回答

1

如果你真的想使用正则表达式,我认为:

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

应该只要你的标题标签没有嵌套工作。正如其他人所说,如果你不控制HTML,正则表达式不是一个很好的方法来做到这一点。

3

当问题是“我如何从HTML中提取东西”时,答案永远不要使用正则表达式。相反,请参阅Robust, Mature HTML Parser for PHP的讨论。

+0

有没有机会举个例子?我需要获取'article'div类中的所有标题标签。我总是对DOm – bluedaniel 2010-01-14 14:44:36

2

建议不要使用正则表达式这个工作,使用的东西SimpleHTMLDOM parser

+0

感到困惑,我发现正则表达式在这方面更好。在解析HTML或无效HTML结构的网页上,DOM解析器有点不可靠。 – 2012-10-30 07:01:43

2

你可能会更好使用HTML解析器。但对于真正简单的场景,这样的事情可能会做:

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

在PHP 5.3.5上使用此片段时,出现错误'preg_match_all():未知修饰符'h';为了解决这个错误,我用管道符号替换了正则表达式边界:''| ([^ <]*) | iU'' – feeela 2011-08-25 14:42:07

3

请考虑本地DOMDocument php类。

您可以使用$domdoc->getElementsByTagName('h1')查看您的标题。

5

首先,你需要清理(在本例中$ html_str)的HTML与整洁:

$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进行更复杂的查询在DOM文档(见http://www.php.net/manual/en/class.domxpath.php

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

东西坏了这个剧本,用简单的HTML喜欢尝试“

测试


” – bluedaniel 2010-01-14 15:04:47

+0

你什么错误如果我尝试的例子,你给它按预期工作?并打印“测试” – CodeAddict 2010-01-14 15:17:10

+0

在所有与唯一的变化是上面的代码:$ xml_str = tidy_repair_string(“

测试


”,$ tidy_config);它打破了我的剧本,有一个错误在那里崩溃像打字错误 – bluedaniel 2010-01-14 15:25:23

3

我知道这是一个超级老帖子,但我想提一提我就能够共同抓住标题标签的最佳方式。

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

这种方法(可以作为一个正则表达式,但是PHP行为有点不同。)在你的preg_match

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

使用本

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

$group[1]将包括曾经是什么在标题标签之间。 $group[0]就是一切<h1>test</h

这将占空间,如果有人添加了 “类/ ID”

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

类/ ID(组)被忽略。

注意:当我分析HTML标签时,我总是将所有空白区域,换行符,制表符等取出并用1个空格替换。这最大限度地减少了多线,dotalls ...和大量的空白,在某些情况下可能会混淆正则表达式格式。

  • 当然我只抓取1-2个标题标签,将其更改为0-9以全部抓取。
  • 如果其他人有一个mod来添加或修复我的代码,请回复,我真的很想知道。
  • 相反,正则表达式对HTML不好,这是一个非常开放的论点。因为如果你设计你的php函数和正则表达式来完美地去掉垃圾并为正则表达式准备HTML,你将会完全能够抓住你正在寻找的东西。你可以做出足够的正则表达式来替代业余html工作。

这里是一个测试页面regex test

+0

我想你是指'| <\ s * h [1-2](?:。*)>(。*) | Ui'否则它不会抓住整个元素并关闭结束标记> 请注意,如果在标题中出现换行符('
'),则完全可能使用用户生成的内容 – cameronjonesweb 2017-11-07 05:44:45

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', 
    ), 
) 
相关问题