【问题标题】:How to extract Heading tags in PHP from a string?如何从字符串中提取 PHP 中的标题标签?
【发布时间】:2011-01-05 02:32:05
【问题描述】:

从包含大量 HTML 的字符串中,如何将 <h1><h2>etc 标记中的所有文本提取到新变量中?

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

可以使用preg_match_all()吗?

【问题讨论】:

标签: php text-extraction domparser


【解决方案1】:

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

【讨论】:

  • 我发现正则表达式在这方面做得更好。 DOM 解析器在 HTML 损坏或 HTML 结构无效的网页上有些不可靠。
  • @datasn.io 在您确定传入的文档包含无效/损坏的 html 之前,您的默认解析选择应该是 DOM 解析器而不是正则表达式。仅当合法解析器无法满足您的需求时才使用正则表达式。
  • @codaddict 这不是一个非常慷慨的答案。
【解决方案2】:

您可能最好使用 HTML 解析器。但对于非常简单的场景,可能会这样做:

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

【讨论】:

    【解决方案3】:

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

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

    只要您的标题标签没有嵌套就应该可以工作。正如其他人所说,如果您无法控制 HTML,则正则表达式不是执行此操作的好方法。

    【讨论】:

    • 这在很多可能的情况下都会失败——比如标题标签有属性的时候。这不是一个稳健或可靠的解决方案。应该在有效的 HTML 上使用合法的 DOM 解析器。
    【解决方案4】:

    也请考虑原生DOMDocument php 类。

    您可以使用$domdoc-&gt;getElementsByTagName('h1') 来获取您的标题。

    【讨论】:

      【解决方案5】:

      首先你需要用 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.net/manual/en/class.domxpath.php

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

      【讨论】:

      • 这个脚本有些问题,用简单的 HTML 试试,比如 '

        Test


        '
      • 你得到什么错误?如果我尝试您给出的示例,它会按预期工作并打印“测试”
      • 和上面的所有代码一样,唯一的变化是:$xml_str = tidy_repair_string('

        Test


        html>', $tidy_config); ???它破坏了我的脚本,那里有一个错误,就像错字或其他东西一样崩溃
      • 我猜你的 php.ini 中没有启用 'tidy' 模块。如果您使用的是 xampp(或其他一些 AMP),请取消注释“extension=php_tidy.dll”行如果您使用的是 Ubuntu,请使用“apt-get install php5-tidy”安装并启用它。
      【解决方案6】:

      我知道这是一篇非常老的帖子,但我想提一下我能够集体抓取标题标签的最佳方式。

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

      此方法(用作正则表达式,但 PHP 的行为有点不同。)

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

      在你的 preg_match 中使用它

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

      $group[1] 将包含标题标签之间的内容。 $group[0] 就是一切 &lt;h1&gt;test&lt;/h

      这将占空间,如果有人添加“class/id”

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

      类/id(组)被忽略。

      注意:当我分析 HTML 标记时,我总是将所有空白、换行符、制表符等删除并替换为 1 个空格。这最大限度地减少了多行、dotalls ......以及非常大量的空白,在某些情况下可能会混淆正则表达式格式。

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

      这里是测试页面的链接regex test

      【讨论】:

      • 我认为你的意思是|&lt;\s*h[1-2](?:.*)&gt;(.*)&lt;/\s*h[1-2]&gt;|Ui 否则它不会抓取整个元素并切断结束标签> 另请注意,如果标题中有换行符(&lt;br/&gt;),这将不匹配如果使用用户生成的内容,这是完全可能的
      • 如果输入是有效的 HTML,任何人都不应该在他们自己的应用程序中实现这一建议。始终使用合法的 DOM 解析器,直到 DOM 解析器不能提供所需的结果。我喜欢正则表达式(很多),但它有一个时间和地点——这不是时间也不是地点。这只是这个正则表达式答案失败的几种方式:3v4l.org/LXXSQ 毫无疑问,“正则表达式是 DOM 无知的”。 IOW,它不知道它是与 DOM 元素的子字符串匹配,还是与基于模式设计的看起来像 DOM 元素的子字符串匹配。
      • @mickmackusa 是的,这是一篇很老的帖子。今天有更好的方法可以做到这一点,但是,我已经使用这种简单的正则表达式技术扫描了超过 500 万个网页,并且没有失败。我会说大多数页面实际上足以使用正则表达式。这些问题可能会发生在低级页面上。但是,是的,如果您想安全,请使用 php 的内置方法来提取 HTML 元素。
      【解决方案7】:

      我只想分享我的解决方案:

      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',
          ),
      )
      

      【讨论】:

        猜你喜欢
        • 2012-06-15
        • 2021-07-30
        • 1970-01-01
        • 2023-01-16
        • 2011-08-21
        • 2014-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多