Instagramに投稿した画像のラベル検出


# 準備
インスタで投稿した画像をラベル検出する方法です。
とりあえず、最後に投稿した画像のラベル検出です。
画像のラベル検出には、GoogleのVison APIを使用します。
実装はPython3.8を使用します。

まず、環境変数を設定します。
インスタのアクセストークン取得方法は以下を参照
https://developers.facebook.com/docs/instagram-basic-display-api/getting-started
アクセスキーを取得する方法は、以下を参照
https://cloud.google.com/vision/docs/detect-labels-image-client-libraries?hl=ja#client-libraries-usage-python

```
export ACCESSTOKEN = <インスタのアクセストークン>
export GOOGLE_APPLICATION_CREDENTIALS = <GoogleCloudのVisonAPIを使用するためのアクセスキー保存先絶対パス>
```

# 実装

```instaLabelDetection.py
import requests
import json
import pprint
import os
import urllib.error
import urllib.request
import visonLabel

#環境変数からアクセストークン取得
accessToken=os.environ["ACCESSTOKEN"]

#インスタ投稿画像リストID取得先エンドポイント
medialist_endpoint="https://graph.instagram.com/{api-version}/{user-id}/media"
params={
    'access_token':accessToken
}
#インスタ投稿画像リスト取得
res = requests.get(medialist_endpoint,params=params)
data = json.loads(res.text)
#最後に投稿した画像リストのID
media_id=data["data"][0]["id"]

#画像URL取得先エンドポイント
mediaurl_endpoint="https://graph.instagram.com/{media_id}".format(media_id=media_id)
params={
    'fields':'media_url',
    'access_token':accessToken
}
#画像URL取得
res = requests.get(mediaurl_endpoint,params=params)
data = json.loads(res.text)
MEDIAURL = data['media_url']
#保存先を指定
dst_url = os.getcwd()+"/insta_post.png"
#画像の保存
try:
    with urllib.request.urlopen(MEDIAURL) as web_file:
        data = web_file.read()
        with open(dst_url,mode='wb') as local_file:
            local_file.write(data)
except urllib.error.URLError as e:
    print(e)

#保存した画像のラベル分析
visonLabel.visonImageLabelDetection(dst_url)
```

### コード解説
APIを実行するには、APIのエンドポイントとパラメータを指定します。
パラメータはJSON形式となります。キーと値が必要です。
```
medialist_endpoint="https://graph.instagram.com/{api-version}/{user-id}/media"
params={
    'access_token':accessToken
}
```
画像リストを取得するには、以下のエンドポイントとパラメータを指定します。

画像リストのエンドポイント: "https://graph.instagram.com/{api-version}/{user-id}/media"
パラメータ:
    　キー:access_token
    　値　: インスタのアクセストークン

次に、エンドポイントとパラメータを指定して、APIを実行します。
```
#インスタ投稿画像リスト取得
res = requests.get(medialist_endpoint,params=params)
```
レスポンスをJSON形式で取得します。JSON内にはインスタに投稿した複数のメディアIDが
含まれています。その中から、最初（最後に投稿した）のメディアIDを取得します。
```
data = json.loads(res.text)
#最後に投稿した画像リストのID
media_id=data["data"][0]["id"]
```

続いて、投稿した画像のURLを取得します。上記で、取得したメディアのIDを
エンドポイントに含め、パラメータは、キーに、filedsとaccess_tokenを指定します。
filedsの値には'media_url'を指定し、access_tokenの値にはインスタのアクセストークンを指定します。

```
mediaurl_endpoint="https://graph.instagram.com/{media_id}".format(media_id=media_id)
params={
    'fields':'media_url',
    'access_token':accessToken
}
```
APIを実行し、投稿した画像のURLを含むJSONを取得します。
```
res = requests.get(mediaurl_endpoint,params=params)
data = json.loads(res.text)
```

JSON内からURLを取得します。
```
MEDIAURL = data['media_url']
```

ラベル検出するために、URL先の画像を保存します。
保存先はpython実行先のディレクトリ内に"insta_post.png"として保存します。
os.getcwd()で実行先ディレクトリを取得し、画像ファイル名を結合します。
```
dst_url = os.getcwd()+"/insta_post.png"
```

取得した画像URLを開き、python実行先のディレクトリ内に、
URL先の画像を保存します。
```
try:
    with urllib.request.urlopen(MEDIAURL) as web_file:
        data = web_file.read()
        with open(dst_url,mode='wb') as local_file:
            local_file.write(data)
except urllib.error.URLError as e:
    print(e)
```

最後に、以下のvisionLavel.pyに保存した画像のパスを渡し、
ラベル検出を実行します。
ラベル検出はアクセスキー取得する際の参照先URLにサンプルあるため、
サンプルをベースに作成
■サンプル
https://cloud.google.com/vision/docs/detect-labels-image-client-libraries?hl=ja#client-libraries-usage-python
今回は、インスタ投稿した画像保存先のパスを"image_path"として、読み込むようにします。

```visonLabel.py
import io

def visonImageLabelDetection(image_path):
    # Imports the Google Cloud client library
    from google.cloud import vision

    # Instantiates a client
    client = vision.ImageAnnotatorClient()

    # Loads the image into memory
    #ここで投稿した画像保存先パス"image_path"を指定し、指定したパスの画像を読み込む。
    with io.open(image_path, 'rb') as image_file:
        content = image_file.read()

    image = vision.Image(content=content)

    # Performs label detection on the image file
    response = client.label_detection(image=image)
    labels = response.label_annotations

    print('Labels:')
    for label in labels:
        print(label.description)
```
# 実行結果
実行すると、以下のように画像から検出したラベルが出力されます。
Labels:
Sky
Leaf
Natural landscape
Twig
Branch
Woody plant
Deciduous
Tints and shades
Flowering plant
Tree


# 最後に
投稿期日指定したり、まとめて検出することもできるようにしたいです。