本篇文章更新時間:2020/09/10
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知。
一介資男的 LINE 社群開站囉!歡迎入群聊聊~


先前有發過一篇 [PHP] 不用 Instagram API 取得照片列表的方法(爬蟲) 有提到 2020/06/29 後「原本」的取得圖文方式會失效,因為 Facebook 正著手整合 Instagram 這個產品進他們現有的系統。

爬蟲那篇文章程式還是可以用,但有一個缺點:沒有寫快取機制、發請求的 IP 如果被 Facebook 給捕捉到異常,就會封鎖導致失效。

簡單來說,就是不算正規的請求做法XD

今天剛好看到這篇 How to display a custom Instagram feed on WordPress after June 2020 有分享新的做法,我就來順著操作與筆記一下!

前置準備

  1. WordPress 網站(本文內程式有使用到 WordPress 快取機制)
  2. Facebook 帳號、Facebook 應用程式
  3. Instagram 帳號
  4. 耐心與好學的心

目前(此文發文日)Facebook 都是使用它的應用程式作為介接平台的中間人角色,所以想要取得平台內容或相關服務,都是必須先申請一個應用程式,這邊就不多介紹了,點上面網址,申請一個就可以!

應用程式加入 Instagram 服務

進入申請好的 Facebook 應用程式裡,左側有個產品區塊可以加入要使用的產品,這邊選擇「Instagram 基本顯示」設定

Instagram

注意 A:不是「Instagram Graph API」哦!我手邊有開過不少的 Facebook 應用程式,目前找不到一個關聯,無法確定為何有些應用程式裡會有「基本顯示」有些則無。所以如果過去開過的應用程式裡找不到,那可以試試看開過一個!

注意 B:這邊看到的特定文字或產品名稱都有可能於日後更新而有所不同。(可能是翻譯成中文或是變更名稱)

建立 Instagram 應用程式

點了上述的「設定」就會到下面這個畫面,然後要建立一個 Instagram 應用程式。

Instagram App

對.. 應用程式裡建立應用程式。這個應用程式只會在 Facebook 這個當前的應用程式裡能使用哦!

點擊建立按鈕後,輸入一個顯示的名稱即可完成這步驟。

建立測試用戶取得授權

這部分要先解釋一下,不論是 Facebook 還是 Instagram 應用程式都會先假定開發者打算將此應用發佈讓公開不特定對象使用,而要正式對外使用的話需要先經過人工審查,超級麻煩!

這邊只是剛好如果把自己納入開發者「測試對象」的話就可以用到全部功能,也是一種非絕對穩定的處理方式,但至少目前「自用」沒問題。

Add or Remove Instagram Testers

上圖中欄位都填寫好(網址URI填你的網站網址),儲存後至下方「Add or Remove Instagram Testers」新增測試員帳號。

輸入你的 Instagram 的 ID 後確認找到自己,然後到 Instagram 後台的設定「應用程式和網站」同意接受測試員角色。

應用程式和網站

這步驟確認完成後回到 Facebook->Instagram 應用程式這邊,會看到自己帳號已經列上去,可以點選「Generate Token」,一路同意授權後,產生存取權杖,記下此碼,後面程式會用到!

在 WordPress 網站上開發

完成上述步驟取得存取權杖後還有一個手續才可以套用首段引用文中的程式碼:取得 Instagram 用戶編號。

這步驟需要先到「存取權杖偵錯工具」把上述存下來的存取權杖放到偵錯欄位中偵錯,會看到「用戶編號」,取得 Instagram 帳號後括弧的數字即可。

存取權杖偵錯工具

存取權杖用戶編號都取得後,就可以套用在下方程式來呼叫 API 拿圖文拉~

<?php 
/**
* 使用 Instagram (Facebook) API 取得用戶圖文的方法,翻譯自原文: https://www.gsarigiannidis.gr/instagram-feed-api-after-june-2020/
*
* @param $token // 存取權杖 
* @param $user // 用戶編號,查詢工具: https://developers.facebook.com/tools/debug/accesstoken/
* @param int $limit // 查詢圖文筆數(不建議設定太多).
* @param string $fields // 其他欄位參考: https://developers.facebook.com/docs/instagram-basic-display-api/reference/media
* @param array $restrict // 取得媒體類型: IMAGE, VIDEO, CAROUSEL_ALBUM
*
* @return array|mixed // 使用方式: get_instagram_media(存取權杖, 用戶編號);
*/
function get_instagram_media(
    $token,
    $user,
    $limit = 10,
    $fields = 'media_url,permalink,media_type,caption',
    $restrict = [ 'IMAGE' ]
) {
    // The request URL. see: https://developers.facebook.com/docs/instagram-basic-display-api/reference/user
    $request_url = 'https://graph.instagram.com/' . $user . '?fields=media&access_token=' . $token;

    // 使用 WordPress Transient API 快取功能一小時更新一次,來避免觸發 Instagram API 存取速率限制 (see: https://developers.facebook.com/docs/graph-api/overview/rate-limiting#instagram-graph-api)
    $output = get_transient( 'instagram_feed_' . $user ); // 使用用戶編號組合成特殊不重複字串來建立快取
    if ( false === ( $data = $output ) || empty( $output ) ) {
        // Prepare the data variable and set it as an empty array.
        $data = [];
        // Make the request
        $response      = wp_safe_remote_get( $request_url );
        $response_body = '';
        if ( is_array( $response ) && ! is_wp_error( $response ) ) {
            $response_body = json_decode( $response['body'] );
        }
        if ( $response_body && isset( $response_body->media->data ) ) {
            $i = 0;
            // Get each media item from it's ID and push it to the $data array.
            foreach ( $response_body->media->data as $media ) {
                if ( $limit > $i ) {
                    $request_media_url = 'https://graph.instagram.com/' . $media->id . '?fields=' . $fields . '&access_token=' . $token;
                    $media_response    = wp_safe_remote_get( $request_media_url );
                    if ( is_array( $media_response ) && ! is_wp_error( $media_response ) ) {
                        $media_body = json_decode( $media_response['body'] );
                    }
                    if ( in_array( $media_body->media_type, $restrict, true ) ) {
                        $i ++;
                        $data[] = $media_body;
                    }
                }
            }
        }
        // Store the data in the transient and keep if for an hour.
        set_transient( 'instagram_feed_' . $user, $data, HOUR_IN_SECONDS );

        // 每次存取都去更新權杖,避免過期不能使用 (see: https://developers.facebook.com/docs/instagram-basic-display-api/guides/long-lived-access-tokens#refresh-a-long-lived-token)
        wp_safe_remote_get( 'https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=' . $token );
        $output = $data;
    }

    return $output;

}

Gist: Link

這方法會拿回 Instagram 裡圖片與描述文的陣列,開發者可以自己去組裝樣式來呈現,這部分就不多寫了!

後記

針對上述方法與程式中最後一段關於更新存取權杖避免過期不能使用的部分,有一個前提!

就是這段程式的方法能不斷的「剛好」因為網站瀏覽,所以去觸發更新。

意思是,如果你網站流量低,有可能一整天都沒人看來觸發的話,那權杖還真有可能會過期,導致無法存取到對應媒體。

這個部分與先前文章記錄過的 WordPress Cron 很類似,可以參考這篇: [WordPress] 詳解定時定期運作的服務: WP-Cron

本篇文章裡的方法還不是一個套上去就能直接用的產品,需要有開發能力的人來繼續客製化調整哦!


Share:

作者: Chun

資訊愛好人士。主張「人人都該為了偷懶而進步」。期許自己成為斜槓到變進度條 100% 的年輕人。[//////////____30%_________]

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *