【问题标题】:Fastest way to retrieve a <title> in PHP在 PHP 中检索 <title> 的最快方法
【发布时间】:2010-09-28 19:10:01
【问题描述】:

我正在做一个书签系统并寻找最快(最简单)的方法来用 PHP 检索页面的标题。

如果有 $title = page_title($url) 这样的东西会很好

【问题讨论】:

    标签: php html parsing


    【解决方案1】:

    我也在做一个书签系统,发现从 PHP 5 开始你可以使用stream_get_line 加载远程页面,直到结束标题标签(而不是加载整个文件),然后摆脱之前的内容以explode 开头的标题标签(而不是regex)。

    function page_title($url) {
      $title = false;
      if ($handle = fopen($url, "r"))  {
        $string = stream_get_line($handle, 0, "</title>");
        fclose($handle);
        $string = (explode("<title", $string))[1];
        if (!empty($string)) {
          $title = trim((explode(">", $string))[1]);
        }
      }
      return $title;
    }
    

    最后 explode 感谢 PlugTrade 的 answer 提醒我标题标签可以有属性。

    【讨论】:

      【解决方案2】:

      或者让这个简单的函数更加防弹:

      function page_title($url) {
      
          $page = file_get_contents($url);
      
          if (!$page) return null;
      
          $matches = array();
      
          if (preg_match('/<title>(.*?)<\/title>/', $page, $matches)) {
              return $matches[1];
          } else {
              return null;
          }
      }
      
      
      echo page_title('http://google.com');
      

      【讨论】:

      • 是的,我被一个带有两个标题标签的页面抓住了一次。在星号后添加问号。
      • 使用@,真的吗?
      • @Louis-MarieMatthews 伙计,这是 2008 年的答案,当时情况完全不同。固定。
      • 奇怪,出于某些原因阅读 2017 年!无论哪种方式,纠正答案永远不会太晚,因为初学者将来可能会访问它。
      【解决方案3】:

      处理添加了属性的标题标签的函数

      function get_title($html)
      {
          preg_match("/<title(.+)<\/title>/siU", $html, $matches);
          if( !empty( $matches[1] ) ) 
          {
              $title = $matches[1];
      
              if( strstr($title, '>') )
              {
                  $title = explode( '>', $title, 2 );
                  $title = $title[1];
      
                  return trim($title);
              }   
          }
      }
      
      $html = '<tiTle class="aunt">jemima</tiTLE>';
      $title = get_title($html);
      echo $title;
      

      【讨论】:

        【解决方案4】:

        不用reg表达式也可以得到:

        $title = '';
        $dom = new DOMDocument();
        
        if($dom->loadHTMLFile($urlpage)) {
            $list = $dom->getElementsByTagName("title");
            if ($list->length > 0) {
                $title = $list->item(0)->textContent;
            }
        }
        

        【讨论】:

        • 这是第一个适用于 deadspin.com 的解决方案
        • 您可能想在使用DOMDocument 之前致电libxml_use_internal_errors(true);。不幸的是,到今天为止,用于解析 HTML (libxml) 的底层库 DOMDocument 仍然不支持 HTML5(毕竟它是一个 XML 库)并且会对 HTML5 语义标签产生警告(例如 &lt;article&gt;&lt;main&gt; )。不幸的是,这里似乎没有替代错误抑制的方法。另见stackoverflow.com/a/6090728/2459834
        【解决方案5】:
        <?php
            function page_title($url) {
                $fp = file_get_contents($url);
                if (!$fp) 
                    return null;
        
                $res = preg_match("/<title>(.*)<\/title>/siU", $fp, $title_matches);
                if (!$res) 
                    return null; 
        
                // Clean up title: remove EOL's and excessive whitespace.
                $title = preg_replace('/\s+/', ' ', $title_matches[1]);
                $title = trim($title);
                return $title;
            }
        ?>
        

        试一试以下输入:

        print page_title("http://www.google.com/");
        

        输出:谷歌

        希望对您的使用足够通用。如果您需要更强大的功能,花点时间研究 HTML 解析器可能不会有什么坏处。

        编辑:添加了一些错误检查。第一个版本有点仓促,抱歉。

        【讨论】:

        • 我比较确定如果找不到模式会产生错误。首先初始化 $title,将 preg_match() 分配给一个布尔值并在尝试访问 $title_matches 数组的第一个元素之前检查它。
        • 哦。太对了。如果 preg_match 没有得到结果,则对 $title_matches 的引用将失败。会整理一下。
        • Facebook 的标题标签如下所示:&lt;title id="pageTitle"&gt;
        【解决方案6】:

        我喜欢将 SimpleXml 与正则表达式一起使用,这是我用来从我创建的 OpenID 库中的页面中获取多个链接标题的解决方案。我已经对其进行了调整以适用于标题(即使通常只有一个)。

        function getTitle($sFile)
        {
            $sData = file_get_contents($sFile);
        
            if(preg_match('/<head.[^>]*>.*<\/head>/is', $sData, $aHead))
            {   
                $sDataHtml = preg_replace('/<(.[^>]*)>/i', strtolower('<$1>'), $aHead[0]);
                $xTitle = simplexml_import_dom(DomDocument::LoadHtml($sDataHtml));
        
                return (string)$xTitle->head->title;
            }
            return null;
        }
        
        echo getTitle('http://stackoverflow.com/questions/399332/fastest-way-to-retrieve-a-title-in-php');
        

        具有讽刺意味的是,这个页面在标题标签中有一个“标题标签”,这有时会导致纯正则表达式解决方案出现问题。

        这个解决方案并不完美,因为如果格式/大小写很重要(例如 XML),它可能会导致嵌套标签出现问题的小写标签,但是有一些方法可以解决这个问题。

        【讨论】:

          【解决方案7】:

          正则表达式?

          使用cURL 获取$htmlSource 变量的内容。

          preg_match('/<title>(.*)<\/title>/iU', $htmlSource, $titleMatches);
          
          print_r($titleMatches);
          

          看看你在那个数组中有什么。

          大多数人说 HTML 遍历虽然你应该使用解析器,因为正则表达式可能不可靠。

          其他答案提供了更多细节:)

          【讨论】:

          • 或许应该改成non greedy来让它更安全
          • 但是我如何获得 $htmlSource 呢?
          • 在这种情况下,我认为可以安全地假设解析器会矫枉过正。 /同意非贪婪匹配
          • 您可以使用 curl 或 fopen 获取 $htmlSource。
          • 我一直在寻找一种更好的方法来做到这一点,但看起来大多数人使用您提出的解决方案作为检索标题的快速方法。请考虑使用 's' 修饰符,我见过一些奇怪的情况,新行打破了正则表达式
          猜你喜欢
          • 1970-01-01
          • 2011-11-08
          • 1970-01-01
          • 2021-09-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-05-04
          相关资源
          最近更新 更多