【问题标题】:How to get Open Graph Protocol of a webpage by php?如何通过php获取网页的开放图协议?
【发布时间】:2011-11-19 06:11:32
【问题描述】:

PHP 有一个简单的命令来获取网页的元标记 (get_meta_tags),但这仅适用于具有名称属性的元标记。然而,Open Graph 协议如今变得越来越流行。从网页获取 opg 值的最简单方法是什么。例如:

<meta property="og:url" content=""> 
<meta property="og:title" content=""> 
<meta property="og:description" content=""> 
<meta property="og:type" content=""> 

我看到的基本方法是通过 cURL 获取页面并使用正则表达式对其进行解析。有什么想法吗?

【问题讨论】:

    标签: php html regex


    【解决方案1】:

    真的很简单,做得很好:

    使用https://github.com/scottmac/opengraph

    $graph = OpenGraph::fetch('http://www.avessotv.com.br/bastidores-pantene-institute-experience-pg.html');
    print_r($graph);
    

    会回来

    OpenGraph 对象

    (
        [_values:OpenGraph:private] => Array
            (
                [type] => article
                [video] => http://www.avessotv.com.br/player/flowplayer/flowplayer-3.2.7.swf?config=%7B%27clip%27%3A%7B%27url%27%3A%27http%3A%2F%2Fwww.avessotv.com.br%2Fmedia%2Fprogramas%2Fpantene.flv%27%7D%7D
                [image] => /wp-content/thumbnails/9025.jpg
                [site_name] => Programa Avesso - Bastidores
                [title] => Bastidores “Pantene Institute Experience†P&G
                [url] => http://www.avessotv.com.br/bastidores-pantene-institute-experience-pg.html
                [description] => Confira os bastidores do Pantene Institute Experience, da Procter &#038; Gamble. www.pantene.com.br Mais imagens:
            )
    
        [_position:OpenGraph:private] => 0
    )
    

    【讨论】:

    • 太棒了!!找了好几个小时,开箱即用!
    • Github 用户 scottmac 似乎已经放弃了他的 OpenGraph 项目,但目前(2016 年初)有一个更新版本,有修复,这里:github.com/AramZS/opengraph
    • 我喜欢这个包,但它不适用于重复的标签,我的意思是它获取最后一个重复的标签,例如 Youtube 正在重复标签(我不知道为什么):youtube.com/embed/C28onNQMXNU">...<metaproperty="og:video:url" content="youtube.com/v/C28onNQMXNU?version=3&amp;autohide=1">,最后一个(也就是这个插件得到的那个)下载一个文件。糟透了 YouTube!
    • 有谁知道为什么这不是从ajio.com/ajio-micro-print-spread-collar-shirt-/p/460292463_blue 等 URL 获取 og:site_name 吗?
    【解决方案2】:

    当从 HTML 解析数据时,你真的不应该使用正则表达式。看看DOMXPath Query function

    现在,实际的代码可能是:

    [编辑] Stefan Gehrig 提供了更好的 XPath 查询,因此代码可以缩短为:

    libxml_use_internal_errors(true); // Yeah if you are so worried about using @ with warnings
    $doc = new DomDocument();
    $doc->loadHTML($html);
    $xpath = new DOMXPath($doc);
    $query = '//*/meta[starts-with(@property, \'og:\')]';
    $metas = $xpath->query($query);
    $rmetas = array();
    foreach ($metas as $meta) {
        $property = $meta->getAttribute('property');
        $content = $meta->getAttribute('content');
        $rmetas[$property] = $content;
    }
    var_dump($rmetas);
    

    而不是:

    $doc = new DomDocument();
    @$doc->loadHTML($html);
    $xpath = new DOMXPath($doc);
    $query = '//*/meta';
    $metas = $xpath->query($query);
    $rmetas = array();
    foreach ($metas as $meta) {
        $property = $meta->getAttribute('property');
        $content = $meta->getAttribute('content');
        if(!empty($property) && preg_match('#^og:#', $property)) {
            $rmetas[$property] = $content;
        }
    }
    var_dump($rmetas);
    

    【讨论】:

    • 老兄,我们生活在一个非想象的世界里,html 并不适合任何地方。在imdb.com/title/tt0120737 上检查您的代码
    • @ 不是解决方案。不要假装没有警告,而是编写一个不发出警告的代码
    • 很好,这是您的解决方案,满意吗? :)
    • 这是为了示例目的,但是现在我想应该没问题?
    • 是的,libxml_use_internal_errors -- 这是完美的解决方案,现在 +1 ;-)
    【解决方案3】:

    怎么样:

    preg_match_all('~<\s*meta\s+property="(og:[^"]+)"\s+content="([^"]*)~i', $str, $matches);
    

    所以,是的,以任何方式抓取页面并使用正则表达式进行解析

    【讨论】:

    • 谢谢,但我希望能找到 preg_match 以外的方法 :)
    • @zerkms 在解析 HTML 时,它比 DomDocument 脏、不可靠且效率低。
    • @Thomas Cantonnet:效率低下?? preg_replaceimdb.com/title/tt0120737 上的速度比您的解决方案快约 100 倍,而且它不会引发任何警告,哈哈?
    • @zerkms 好吧,试试你的代码: 有用吗?不。 有用吗?没有。
    • 大家好,从某种意义上说,你们俩都是对的。 preg_match 快速但不可靠。 DOM 是可靠的,但速度很慢,而且消耗资源。我个人更喜欢 preg_match 但结构上的微小变化可能会毁掉你的整个世界。
    【解决方案4】:

    此函数无需依赖和 DOM 解析即可完成工作:

    function getOgTags($html)
    {
        $pattern='/<\s*meta\s+property="og:([^"]+)"\s+content="([^"]*)/i';
        if(preg_match_all($pattern, $html, $out))
            return array_combine($out[1], $out[2]);
        return array();
    }
    

    测试代码:

    $x=' <title>php - Using domDocument, and parsing info, I would like to get the &#39;href&#39; contents of an &#39;a&#39; tag - Stack Overflow</title>
            <link rel="shortcut icon" href="https://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico?v=4f32ecc8f43d">
            <link rel="apple-touch-icon image_src" href="https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon.png?v=c78bd457575a">
            <link rel="search" type="application/opensearchdescription+xml" title="Stack Overflow" href="/opensearch.xml">
            <meta name="referrer" content="origin" />
    
    
            <meta property="og:type" content="website"/>
            <meta property="og:url" content="https://stackoverflow.com/questions/5278418/using-domdocument-and-parsing-info-i-would-like-to-get-the-href-contents-of"/>
            <meta property="og:image" itemprop="image primaryImageOfPage" content="https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon@2.png?v=73d79a89bded" />
            <meta name="twitter:card" content="summary"/>
            <meta name="twitter:domain" content="stackoverflow.com"/>
            <meta name="twitter:title" property="og:title" itemprop="title name" content="Using domDocument, and parsing info, I would like to get the &#39;href&#39; contents of an &#39;a&#39; tag" />
            <meta name="twitter:description" property="og:description" itemprop="description" content="Possible Duplicate:
      Regular expression for grabbing the href attribute of an A element  
    This displays the what is between the a tag, but I would like a way to get the href contents as well.
    
    Is..." />';
    echo '<pre>';
    var_dump(getOgTags($x));
    

    你会得到:

    array(3) {
      ["type"]=>
      string(7) "website"
      ["url"]=>
      string(119) "https://stackoverflow.com/questions/5278418/using-domdocument-and-parsing-info-i-would-like-to-get-the-href-contents-of"
      ["image"]=>
      string(85) "https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon@2.png?v=73d79a89bded"
    }
    

    【讨论】:

      【解决方案5】:

      按照此方法,您将获得 fabcebook 开放图形标签的密钥对数组。

       $url="http://fbcpictures.in";
       $site_html=  file_get_contents($url);
          $matches=null;
          preg_match_all('~<\s*meta\s+property="(og:[^"]+)"\s+content="([^"]*)~i',     $site_html,$matches);
          $ogtags=array();
          for($i=0;$i<count($matches[1]);$i++)
          {
              $ogtags[$matches[1][$i]]=$matches[2][$i];
          }
      

      【讨论】:

        【解决方案6】:

        这是我用来提取 Og 标签的。

        function get_og_tags($get_url = "", $ret = 0)
        {
        
            if ($get_url != "") {
                $title = "";
                $description = "";
                $keywords = "";
                $og_title = "";
                $og_image = "";
                $og_url = "";
                $og_description = "";
                $full_link = "";
                $image_urls = array();
                $og_video_name = "";
                $youtube_video_url="";
        
                $get_url = $get_url;
        
                $ret_data = file_get_contents_curl($get_url);
                //$html = file_get_contents($get_url);
        
                $html = $ret_data['curlData'];
                $full_link = $ret_data['full_link'];
        
                $full_link = addhttp($full_link);
        
        
                //parsing begins here:
                $doc = new DOMDocument();
                @$doc->loadHTML($html);
                $nodes = $doc->getElementsByTagName('title');
                if ($nodes->length == 0) {
                    $title = $get_url;
                } else {
                    $title = $nodes->item(0)->nodeValue;
                }
                //get and display what you need:
                $metas = $doc->getElementsByTagName('meta');
                for ($i = 0; $i < $metas->length; $i++) {
                    $meta = $metas->item($i);
                    if ($meta->getAttribute('name') == 'description')
                        $description = $meta->getAttribute('content');
                    if ($meta->getAttribute('name') == 'keywords')
                        $keywords = $meta->getAttribute('content');
                }
                $og = $doc->getElementsByTagName('og');
                for ($i = 0; $i < $metas->length; $i++) {
                    $meta = $metas->item($i);
                    if ($meta->getAttribute('property') == 'og:title')
                        $og_title = $meta->getAttribute('content');
        
                    if ($meta->getAttribute('property') == 'og:url')
                        $og_url = $meta->getAttribute('content');
        
                    if ($meta->getAttribute('property') == 'og:image')
                        $og_image = $meta->getAttribute('content');
        
                    if ($meta->getAttribute('property') == 'og:description')
                        $og_description = $meta->getAttribute('content');
        
                    // for sociotube video share 
                    if ($meta->getAttribute('property') == 'og:video_name')
                        $og_video_name = $meta->getAttribute('content'); 
        
                    // for sociotube youtube video share 
                    if ($meta->getAttribute('property') == 'og:youtube_video_url')
                        $youtube_video_url = $meta->getAttribute('content');    
        
                }
        
                //if no image found grab images from body
                if ($og_image != "") {
                    $image_urls[] = $og_image;
                } else {
                    $xpath = new DOMXPath($doc);
                    $nodelist = $xpath->query("//img"); // find your image
                    $imgCount = 0;
        
                    for ($i = 0; $i < $nodelist->length; $i++) {
                        $node = $nodelist->item($i); // gets the 1st image
                        if (isset($node->attributes->getNamedItem('src')->nodeValue)) {
                            $src = $node->attributes->getNamedItem('src')->nodeValue;
                        }
                        if (isset($node->attributes->getNamedItem('src')->value)) {
                            $src = $node->attributes->getNamedItem('src')->value;
                        }
                        if (isset($src)) {
                            if (!preg_match('/blank.(.*)/i', $src) && filter_var($src, FILTER_VALIDATE_URL)) {
                                $image_urls[] = $src;
                                if ($imgCount == 10) break;
                                $imgCount++;
                            }
                        }
                    }
                }
        
                $page_title = ($og_title == "") ? $title : $og_title;
                if(!empty($og_video_name)){
                    // for sociotube video share 
                    $page_body = $og_video_name;
                }else{
                    // for post share 
                   $page_body = ($og_description == "") ? $description : $og_description; 
                }
        
                $output = array('title' => $page_title, 'images' => $image_urls, 'content' => $page_body, 'link' => $full_link,'video_name'=>$og_video_name,'youtube_video_url'=>$youtube_video_url);
                if ($ret == 1) {
                    return $output; //output JSON data
                }
                echo json_encode($output); //output JSON data
        
                die;
            } else {
                $data = array('error' => "Url not found");
                if ($ret == 1) {
                    return $data; //output JSON data
                }
                echo json_encode($data);
                die;
            }
        }
        

        函数的使用

        $url = "https://www.alectronics.com";
        $tagsArray = get_og_tags($url);
        print_r($tagsArray);
        

        【讨论】:

          【解决方案7】:

          XMLish 更多的方式是使用 XPath:

          $xml = simplexml_load_file('http://ogp.me/');
          $xml->registerXPathNamespace('h', 'http://www.w3.org/1999/xhtml');
          $result = array();
          foreach ($xml->xpath('//h:meta[starts-with(@property, \'og:\')]') as $meta) {
              $result[(string)$meta['property']]  = (string)$meta['content'];
          }
          print_r($result);
          

          不幸的是,如果 HTML 文档在 &lt;html&gt;-tag 中使用命名空间声明,则需要命名空间注册。

          【讨论】:

          • imdb.com/title/tt0120737 试试你的代码 ;-) 收到了很长的警告列表
          • 没有必要在这里发起某种激烈的争吵......我实际上会选择preg_match-解决方案,但我只是想展示一种不同且更优雅的方法 - 不幸的是确实有一些现实世界中的问题(通常是由于使用了 HTML 实体或未转义的字符,如 &lt;&gt;&amp; 等)
          • 那么,它与不可预知的结果相关联;因为在 html 网页中使用了广泛的命名空间。但我很欣赏你的思维方式!
          • 你是对的。该方法更适合您了解文档的受控环境。命名空间问题可以通过检查声明的命名空间来解决,所以在我看来,更大的问题是大多数 HTML 文档远离标准。
          【解决方案8】:

          使用原生 PHP 函数 get_meta_tags()。

          https://php.net/get_meta_tags

          【讨论】:

          • 如问题中所述,“这仅适用于具有名称属性的元标记”,而 Open Graph 元标记没有,因此对于所需目的完全无用。
          猜你喜欢
          • 2016-01-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多