Facebook有时无法获取Open Graph标签。

10
我有一个iOS应用程序,为公共图书馆提供链接分享到Facebook。这些链接指向单个域,其中包含一个相对简单的PHP脚本,根据链接内容(目录项目、日历事件和用户生成的列表)重定向到三个不同的目标域。我这样设置是因为我正在使用iOS通用链接,并且我无法控制所有链接目标,因此需要一个中央位置来存放apple-app-site-association文件。
在这个PHP脚本中,我试图根据分享的内容类型动态设置OG标签。以下是脚本:
<?php

$shareType = $_GET['t'];
$contentId = $_GET['id'];

$base_catalog_url='XXXXXXXXXXXX';
$base_list_url='XXXXXXXXXXXXX';
$base_event_url='XXXXXXXXXXXXXX';

if($shareType=='0'){
    $oclc;
    if(strlen($contentId)==8){
        $oclc = 'ocm'.$contentId;
    }

    if(strlen($contentId)==9){
        $oclc = 'ocn'.$contentId;
    }

    $url = $base_catalog_url.'searchCatalog?'.http_build_query(array('clientID' =>'sdIPhoneApp','term1'=>$oclc));
    $resp = simplexml_load_file($url);

    $pageTitle = $resp->HitlistTitleInfo->title;
    $isbn = $resp->HitlistTitleInfo->ISBN;
    $imageURL = 'http://www.syndetics.com/index.aspx?isbn='.$isbn.'/lc.gif&client=XXXXXXX';
    $redirectURL =  'XXXXXXXXXXXX'.$contentId;
    error_log($redirectURL);
    echo '<html>
        <head>
            <meta property="og:image" content="'.$imageURL.'" />
            <meta property="og:title" content="'.$pageTitle.'" />
            <meta name="twitter:card" content="summary" />
            <meta name="twitter:site" content="@acpl" />
            <meta name="twitter:title" content="'.$pageTitle.'" />
            <meta name="twitter:description" content="Allen County Public Library" />
            <meta name="twitter:image" content="'.$imageURL.'" />
            <meta http-equiv="refresh" content="0;URL='.$redirectURL.'">
        </head>
     </html>';
}

if($shareType=='1'){
    $url = $base_event_url.http_build_query(array('eventid' =>$contentId));
        $response = file_get_contents($url);
    $json = json_decode($response);
    $event = $json[0];
    $imageURL = $event->Image;
    $pageTitle = $event->Title;
    $description = $event->Description;

    if(strlen($imageURL)<5){
        $imageURL = 'https://XXXXXXXXX/appIcon200.png';
    }

    $redirectURL = 'XXXXXXXXXXX'.$contentId;

    echo '<html>
        <head>
            <meta property="og:image" content="'.$imageURL.'" />
            <meta property="og:title" content="'.$pageTitle.'" />
            <meta property="og:description" content="'.$description.'" />
            <meta name="twitter:card" content="summary" />
            <meta name="twitter:site" content="@acpl" />
            <meta name="twitter:title" content="'.$pageTitle.'" />
            <meta name="twitter:description" content="'.$description.'" />
            <meta name="twitter:text:description" content="'.$description.'" />
            <meta name="twitter:image" content="'.$imageURL.'" />
            <meta http-equiv="refresh" content="0;URL='.$redirectURL.'">
        </head>
     </html>';

}

if($shareType=='2'){

    $url = $base_list_url.http_build_query(array('listId' =>$contentId,'userKey'=>0));
    $response = file_get_contents($url);
    $json = json_decode($response);
    $imageURL = $json->coverImageURL;
    $pageTitle = $json->listName;
    $pageTitle = ucwords(strtolower($pageTitle));

    $redirectURL = "XXXXXXXXXXXX";

    echo '<html>
        <head>
            <meta property="og:image" content="'.$imageURL.'" />
            <meta property="og:title" content="'.$pageTitle.'" />
            <meta name="twitter:card" content="summary" />
            <meta name="twitter:site" content="@acpl" />
            <meta name="twitter:title" content="'.$pageTitle.'" />
            <meta name="twitter:description" content="Allen County Public Library" />
            <meta name="twitter:image" content="'.$imageURL.'" />
            <meta http-equiv="refresh" content="0;URL='.$redirectURL.'">
        </head>
     </html>';

}

?>

所以,基于分享的内容类型,我获取页面标题和图片,提供OG标签。重定向总是有效的,无论Facebook是否拉取标签,但标签仅有一半的时间被使用。您可以在iOS应用程序中看到这一点。成功获取的标签:

enter image description here

标签未被拉取:

enter image description here

对于某个项目,标签是否显示似乎是随机的。在我的服务器访问日志中,当标签成功显示时,我会看到这样一行:

66.220.158.119 - - [09/Sep/2016:09:54:50 -0400] "GET /share.php?t=1&id=76137 HTTP/1.1" 206 3771 "-" "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)"

然而,当标签未显示时,访问日志或错误日志中没有任何内容。这表明Facebook(或iOS中的Facebook组件)在这些情况下甚至没有尝试读取标签。这是否意味着Facebook错误地认为它已经缓存了这些数据?
另一个有趣的细节是,当我尝试在Facebook共享调试器(https://developers.facebook.com/tools/debug/)上调试其中一个失败的URL时会发生什么。我会收到类似以下的错误消息:
The 'og:image' property should be explicitly provided, even if a value can be inferred from other tags.

当我点击“查看我们的爬虫为您的URL看到的内容”时,会得到“文档未返回任何数据”的响应。有趣的是,当我点击“再次抓取”时,通常在前几次尝试中都会出现同样的错误,然后经过3或4次尝试后,它突然开始工作并显示标签。我的第一反应是这与我如何动态获取标签内容有关,但正如我上面所提到的,在标签未显示的情况下,访问日志显示Facebook甚至没有从我的服务器请求任何内容。谢谢你的帮助,这让我抓狂了!更新:如果您想尝试,请使用以下示例URL在Facebook调试器中进行测试:https://amshare.acpl.lib.in.us/0_930144011 下划线后面的数字是该书的OCLC编号,因此您可以在那里插入其他值。正如我所提到的,经过几次抓取后,它通常开始工作,然后再次失败等等。

是的,它总是share.php。我想我可以为每种分享类型使用不同的脚本(shareItem.php、shareEvent.php),但似乎这将面临相同的基本问题。 - James Harpe
我认为你可能需要为每个链接使用唯一的URL。如果你看一下URL缩短服务(Bit.ly,Goo.gl等)和其他依赖于每个URL跟踪或动态路由(HubSpot,HootSuite)的服务,它们普遍采用这种方式。在Branch.io,我们几乎完全按照你上面描述的方式进行操作,每个链接始终都带有唯一的URL。 - Alex Bauer
如果我这样做,就无法利用通用链接。 - James Harpe
仍应该能够。只需将所有唯一的URL放在单个目录下面(例如,/share/7ahAs7D),然后为该目录中的所有内容启用通用链接。 - Alex Bauer
@AlexBauer 很抱歉,我没有什么好运气。我正在重写URL,使它们看起来像“http://XXXX/type/idnumber”,以便每个URL都是唯一的,但我仍然得到相同的行为。我会坚持使用这些URL,因为它们更短,但原始问题仍然存在。 - James Harpe
显示剩余9条评论
2个回答

1

Facebook可能会缓存share.php文件并忽略GET变量。

你可以尝试将URL重写为“美化永久链接”。如果你使用的是Apache服务器,可以在htaccess文件中添加以下代码:

Options +FollowSymLinks
RewriteEngine On

RewriteRule ^share/(.*)/(.*)$ share.php?t=$1&id=$2 [L,NC]

这将从http://your-url.com/share/4/yeah生成http://your-url.com/?t=4&id=yeah

$_GET变量看起来像这样:

Array ( [t] => 4 [id] => yeah )

如果这确实是缓存问题,您可以使用此方法解决。我过去曾经遇到过很多Facebook爬虫的问题。有时它会忽略get变量并且缓存非常厉害...


在进行这个更改之后,我看到的行为是一样的。而且,我可以肯定地说这几乎肯定是某种缓存问题。就像我上面提到的,在标签不起作用的情况下,访问日志中绝对没有任何内容。所以在这些情况下,Facebook并未从我的服务器请求任何内容。 - James Harpe
你尝试过使用与sharer.php URL完全相同的og:url元标记添加吗?(或者如果您插入了我的代码片段,则进行了重写)这会告诉FB抓取其中的URL-可能可以解决您的缓存问题。 - Adrian Lambertz
我已经尝试过这个方法,但结果却相同。当我在调试器上告诉它“再次抓取”的时候,它似乎完全是随机的,无论成功与否。 - James Harpe
你能发布一个分享的URL吗?这样我就可以自己测试一下会发生什么了。 - Adrian Lambertz
下划线后面的数字是书籍的OCLC编号,因此您可以尝试在那里插入其他值。正如我所提到的,经过几次抓取后,它通常开始工作,然后再次失败,依此类推。 - James Harpe
显示剩余2条评论

0

尝试在响应中添加一些头部以防止缓存。

Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Expires: 0


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接