Facebook API - 如何通过Facebook API获取用户的个人资料图片(无需要求用户“允许”应用程序)

261
我正在开发一个CMS,它从用户的Facebook URL(即http://facebook.com/users_unique_url)获取用户的个人资料图片。我该如何实现这一点?是否有Faceboook API调用可以获取用户的个人资料图片URL,而无需用户允许应用程序?
14个回答

410

74
继续查看该页面,另一个有用的东西可能是您可以添加的?type=large查询字符串。顺便说一下,您提供的答案比我正在输入的屏幕抓取要好多了 :). - Domenic
6
如果在HTTP和HTTPS之间切换,请使用<img src="//graph.facebook.com/sarfraz.anees/picture" />。浏览器会检测协议,因此在HTTPS上你不会收到混合内容警告。请注意,翻译后的内容应该与原始内容保持一致,且不需要解释或提供额外的信息。 - Chris Jacob
39
需要强调的是,一些用户在其FB账户上没有设置用户名。当出现这种情况,并且您尝试实施此答案时,您将收到FB的默认个人资料图片,即问号。为了轻松避免这个问题,可以使用用户的FB ID代替用户名。 - Josh
8
需要注意的是,在图形 API 的 V2 版本中,使用用户名将不再起作用。现在您需要首先获取用户 ID,不能再使用用户名获取。每个应用程序的用户 ID 也会更改,因此您必须具有某种适当的身份验证才能检索可用的用户 ID。从技术上讲,个人资料图片仍然是公开的,并可在 http://graph.facebook.com/v2.2/4/picture?redirect=0 上获得,但根据用户个人资料信息仅凭图片链接无法确定用户 ID(前文链接中的 4)。旧的图形 URL 在 2015 年 4 月之前仍然可用。 - sckd
37
2015年,我遇到了“(#803)无法按用户名(sarfraz.anees)查询用户”的问题。 - Santosh Kumar
显示剩余12条评论

268

展示如下:

50x50 像素

<img src="//graph.facebook.com/{{fid}}/picture">

200像素宽度

<img src="//graph.facebook.com/{{fid}}/picture?type=large">

使用PHP进行保存

注意: 不要使用此方法,请查看下面 @Foreever 的评论。

$img = file_get_contents('https://graph.facebook.com/'.$fid.'/picture?type=large');
$file = dirname(__file__).'/avatar/'.$fid.'.jpg';
file_put_contents($file, $img);

在这里,$fid 是您在 Facebook 上的用户 ID。

注意:对于标记为“18+”的图片,您需要来自一个 18+ 用户的有效 access_token:

<img src="//graph.facebook.com/{{fid}}/picture?access_token={{access_token}}">

更新2015:

Graph API v2.0不能使用用户名进行查询,你应该始终使用userId


6
以下是类型参数的更多信息:"您可以使用type参数指定所需的图片大小,该参数应为以下之一:square(50x50)、small(50像素宽,高度可变)、normal(100像素宽,高度可变)和large(大约200像素宽,高度可变)"。 来自Facebook Graph API - user603284
3
为使用此方法,您需要将 allow_url_fopen 设置为 on。allow_url_fopen 指令默认情况下处于禁用状态。启用 allow_url_fopen 指令会存在安全隐患,因为能够访问远程文件的 PHP 脚本可能会受到任意代码注入攻击。当 allow_url_fopen 指令启用时,您可以编写脚本以打开远程文件,就像它们是本地文件一样。 - Foreever
看起来很有用,提前感谢,但我太新手了,不理解这是哪种编程语言?我猜测是PHP。 - hello_there_andy
@hello_there_andy 是的!这是 PHP(实际上,该问题已标记为 PHP,而且 4 年前我所使用的唯一语言也是 PHP)。 - neiker
谢谢,伙计。我在 API 文档和 Graph Explorer 上花了大约 2 小时搜索,但没有找到。 - Antwan
7
2015年7月之后,这个方法已经失效了(出现错误:“无法通过用户名查询用户”)。 - Flimm

164

更新:

从2012年8月底开始,API已经更新,允许您检索用户的个人资料图片以不同的尺寸。将可选的宽度和高度字段添加为URL参数:

https://graph.facebook.com/USER_ID/picture?width=WIDTH&height=HEIGHT

其中WIDTHHEIGHT是您请求的尺寸参数。

这将返回一个最小尺寸为WIDTH x HEIGHT的个人资料图片,并尝试保持其宽高比。例如,

https://graph.facebook.com/redbull/picture?width=140&height=110

返回

    {
      "data": {
        "url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-ash4/c0.19.180.142/s148x148/2624_134501175351_4831452_a.jpg",
        "width": 148,
        "height": 117,
        "is_silhouette": false
      }
   }

更新结束

要获取用户的个人资料图片,请调用以下方法:

https://graph.facebook.com/USER_ID/picture

其中USER_ID可以是用户ID号码或用户名。

要获取特定尺寸的用户个人资料图片,请调用

https://graph.facebook.com/USER_ID/picture?type=SIZE

在这里,SIZE应该被替换成其中一个单词。

square
small
normal
large

根据您想要的尺寸,此调用将返回一个URL,其中包含基于您选择的类型参数的单个图像。

例如:

https://graph.facebook.com/USER_ID/picture?type=small

返回图像的小版本的URL。

API 仅指定了个人资料图像的最大尺寸,而不是实际大小。

正方形:

最大宽度和高度为50像素。

小型:

最大宽度为50像素,最大高度为150像素。

普通:

最大宽度为100像素,最大高度为300像素。

大型:

最大宽度为200像素,最大高度为600像素。

如果调用默认 USER_ID/picture,则会获取正方形类型。

澄清

如果按照上面的示例进行调用,则会获取正方形类型。

https://graph.facebook.com/redbull/picture?width=140&height=110

如果您使用Facebook SDK的请求方法之一,它将返回一个JSON响应。否则,它将返回图片本身。要始终检索JSON,请添加:

&redirect=false

像这样:

https://graph.facebook.com/redbull/picture?width=140&height=110&redirect=false

我仍然得到与我的答案相同的响应。您可以在Facebook开发人员的Graph Explorer上尝试它,网址为developers.facebook.com/tools/explorer。输入“redbull/picture?width=140&height=110”,并查看响应。我的答案假定您正在使用Facebook SDK API /请求方法之一调用此功能,该方法将返回JSON响应。 - Gunnar Karlsson
2
@GunnarKarlsson 你漏掉了 &redirect=false,应该加上以返回 JSON 数据而不是重定向到图片。 - andrewtweber
@andrewtweber 非常感谢。我已经在答案中添加了澄清。 - Gunnar Karlsson
不错啊...帮了我很多...我一开始对Facebook SDK感到陌生,但你让我感觉很舒适... - anuj arora
3
现在是2015年7月,这个不再起作用了。(错误信息:“无法按用户名查询用户”) - Flimm
显示剩余2条评论

20
获取图像URL,而非二进制内容:
$url = "http://graph.facebook.com/$fbId/picture?type=$size";

$headers = get_headers($url, 1);

if( isset($headers['Location']) )
    echo $headers['Location']; // string
else
    echo "ERROR";

你必须使用你的FACEBOOK ID,而不是用户名。你可以在这里获取你的facebook id:

http://findmyfbid.com/


1
现在是2015年7月,这个不再起作用了(错误:“无法按用户名查询用户”) - Flimm
3
你误解了,朋友 :) 它是你的 Facebook ID,而不是用户名 http://findmyfbid.com/ - NaturalBornCamper
1
最好在这里。这绝对是疯狂的,我试图在正文中获取数据,然后数据出现在标题中 @.@ - Davuz

19

一个简单的一行代码,可以将完整尺寸的个人资料图片保存在您的服务器上。

<?php

copy("https://graph.facebook.com/FACEBOOKID/picture?width=9999&height=9999", "picture.jpg");

?>

只有在php.ini启用了openssl才能使其工作。


现在是2015年7月,这个不再起作用了(错误:“无法按用户名查询用户”) - Flimm
是的,v1.0的调用将在2015年4月30日后停止工作。除非用户授权您的应用程序,否则无法获取特定于应用程序的ID。 - Armand

11

添加了对已接受答案的评论,但觉得它值得进一步解释。自2015年4月左右开始,这可能会被提起多次。

自图形API V2推出后,使用用户名的已接受答案不再适用。现在你需要先获取userid,而你不能再使用用户名来获取它。为了进一步复杂化问题,出于隐私原因,Facebook正在更改每个应用程序的userid(请参见https://developers.facebook.com/docs/graph-api/reference/v2.2/user/https://developers.facebook.com/docs/apps/upgrading/#upgrading_v2_0_user_ids),因此你将需要某种适当的身份验证才能检索到可用的userid。从技术上讲,个人资料图片仍然是公开的,并可在/ userid / picture中使用(请参见https://developers.facebook.com/docs/graph-api/reference/v2.0/user/picture和此示例用户:http://graph.facebook.com/v2.2/4/picture?redirect=0)。但是,仅凭他们的个人资料信息似乎无法找到用户的标准userid-你的应用程序需要让他们批准与应用程序的交互,而对于我的用例(仅在他们的FB个人资料链接旁边显示个人资料图片),这太过麻烦。

如果有人已经找到了根据用户名获取个人资料图片的方法,或者另外一种获取userid(即使是备用的)以用来检索个人资料图片的方法,请分享!同时,旧的图形URL仍然有效,直到2015年4月。


9

这是一个2015年4月的PHP(HTTP GET)工作解决方案(不需要PHP 5 SDK):

function get_facebook_user_avatar($fbId){
        $json = file_get_contents('https://graph.facebook.com/v2.5/'.$fbId.'/picture?type=large&redirect=false');
        $picture = json_decode($json, true);
        return $picture['data']['url'];
}

你可以在参数中更改'type':
正方形:
最大宽度和高度为50像素。
小号:
最大宽度为50像素,最大高度为150像素。
普通:
最大宽度为100像素,最大高度为300像素。
大号:
最大宽度为200像素,最大高度为600像素。

9

有一种方法是使用Gamlet在他的回答中发布的代码:

  • Save it as curl.php

  • Then in your file:

    require 'curl.php';
    
    $photo="https://graph.facebook.com/me/picture?access_token=" . $session['access_token'];
    $sample = new sfFacebookPhoto;
    $thephotoURL = $sample->getRealUrl($photo);
    echo $thephotoURL;
    

我想分享这个内容,因为我花了一些时间才弄清楚具体细节...即使个人资料图片是公开的,当你使用cURL时仍需要在其中加入访问令牌才能获取它。


8

有一种方法可以做到这一点 ;)

感谢 "http://it.toolbox.com/wiki/index.php/Use_curl_from_PHP_-_processing_response_headers" 提供的帮助:

<?php

    /**
     * Facebook user photo downloader
     */

    class sfFacebookPhoto {

        private $useragent = 'Loximi sfFacebookPhoto PHP5 (cURL)';
        private $curl = null;
        private $response_meta_info = array();
        private $header = array(
                "Accept-Encoding: gzip,deflate",
                "Accept-Charset: utf-8;q=0.7,*;q=0.7",
                "Connection: close"
            );

        public function __construct() {
            $this->curl = curl_init();
            register_shutdown_function(array($this, 'shutdown'));
        }

        /**
         * Get the real URL for the picture to use after
         */
        public function getRealUrl($photoLink) {
            curl_setopt($this->curl, CURLOPT_HTTPHEADER, $this->header);
            curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, false);
            curl_setopt($this->curl, CURLOPT_HEADER, false);
            curl_setopt($this->curl, CURLOPT_USERAGENT, $this->useragent);
            curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT, 10);
            curl_setopt($this->curl, CURLOPT_TIMEOUT, 15);
            curl_setopt($this->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
            curl_setopt($this->curl, CURLOPT_URL, $photoLink);

            //This assumes your code is into a class method, and
            //uses $this->readHeader as the callback function.
            curl_setopt($this->curl, CURLOPT_HEADERFUNCTION, array(&$this, 'readHeader'));
            $response = curl_exec($this->curl);
            if (!curl_errno($this->curl)) {
                $info = curl_getinfo($this->curl);
                var_dump($info);
                if ($info["http_code"] == 302) {
                    $headers = $this->getHeaders();
                    if (isset($headers['fileUrl'])) {
                        return $headers['fileUrl'];
                    }
                }
            }
            return false;
        }


        /**
         * Download Facebook user photo
         *
         */
        public function download($fileName) {
            curl_setopt($this->curl, CURLOPT_HTTPHEADER, $this->header);
            curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($this->curl, CURLOPT_HEADER, false);
            curl_setopt($this->curl, CURLOPT_USERAGENT, $this->useragent);
            curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT, 10);
            curl_setopt($this->curl, CURLOPT_TIMEOUT, 15);
            curl_setopt($this->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
            curl_setopt($this->curl, CURLOPT_URL, $fileName);
            $response = curl_exec($this->curl);
            $return = false;
            if (!curl_errno($this->curl)) {
                $parts = explode('.', $fileName);
                $ext = array_pop($parts);
                $return = sfConfig::get('sf_upload_dir') . '/tmp/' . uniqid('fbphoto') . '.' . $ext;
                file_put_contents($return, $response);
            }
            return $return;
        }

        /**
         * cURL callback function for reading and processing headers.
         * Override this for your needs.
         *
         * @param object $ch
         * @param string $header
         * @return integer
         */
        private function readHeader($ch, $header) {

            //Extracting example data: filename from header field Content-Disposition
            $filename = $this->extractCustomHeader('Location: ', '\n', $header);
            if ($filename) {
                $this->response_meta_info['fileUrl'] = trim($filename);
            }
            return strlen($header);
        }

        private function extractCustomHeader($start, $end, $header) {
            $pattern = '/'. $start .'(.*?)'. $end .'/';
            if (preg_match($pattern, $header, $result)) {
                return $result[1];
            }
            else {
                return false;
            }
        }

        public function getHeaders() {
            return $this->response_meta_info;
        }

        /**
         * Cleanup resources
         */
        public function shutdown() {
            if($this->curl) {
                curl_close($this->curl);
            }
        }
    }

7
我在思考 - 或许 ID 将会是一个有用的工具。每当用户创建一个新账户时,它应该获得更高的ID。我搜索了一下,发现有一种方法可以通过ID估计账户创建日期,来自metadatascience.com的Massoud Seifi收集了一些好的数据。

Enter image description here

阅读本文:

http://metadatascience.com/2013/03/11/inferring-facebook-account-creation-date-from-facebook-user-id/

这里是一些可供下载的ID:

http://metadatascience.com/2013/03/14/lookup-table-for-inferring-facebook-account-creation-date-from-facebook-user-id/


2
这个回答如何回答问题? - Flimm

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