twitterで画像のツイートのみ取得する


はじめに

私はTwitterで育児漫画を読むことが多いのですが、
漫画以外のツイートもタイムラインに表示されると鬱陶しいので、
漫画(=画像)のツイートのみをTwitter APIを使って取得します。

処理フロー

1.自分がフォローしているユーザーを取得(Twitter API)
2.各ユーザーのタイムラインを取得(Twitter API)
3.ツイート内容から画像有無を判定
4.画像があるものをいいね&リツイート(Twitter API)

こうすると自分のタイムラインを表示すれば、画像のツイートのみをまとめて閲覧できます。

実装

Twitter APIの認証

API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRETは以下のサイトを参考に取得しました。
2020年度版 Twitter API利用申請の例文からAPIキーの取得まで詳しく解説

twitter = OAuth1Session(API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

1.自分がフォローしているユーザーを取得

まず自分がフォローしているユーザーのユーザー名(正確にはscreen name)を取得します。
エンドポイントは https://api.twitter.com/1.1/friends/list.json を使用します。
最大200人がAPIの制限のようです。
引数のscreen_nameには自分のscreen_nameを指定します。
(他の人のscreen nameでも取得はできます)

get_follow_screen_name
def get_follow_screen_name(screen_name):
    # 空のリストを用意
    follow_list = []

    # 認証
    twitter = OAuth1Session(API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
    # 取得エンドポイント
    url = "https://api.twitter.com/1.1/friends/list.json"
    # パラメータ
    params = {"screen_name": screen_name, "count": 200}

    # リクエスト
    res = twitter.get(url, params=params)

    if res.status_code == 200:
        result_json = json.loads(res.text)
        # リストにフォロー者を追加
        for i in range(0, len(result_json["users"]), 1):
            follow_list.append(result_json["users"][i]["screen_name"])
        # リストを返す
        return follow_list
    else:
        return None

2.各ユーザーのタイムラインを取得

1で取得した各ユーザーのscreen_nameを使用し、タイムラインを取得してJSON形式で返します。
今回は最新のツイートが欲しいので、count=1としています。

get_user_timeline
def get_user_timeline(screen_name):
    # 認証処理
    twitter = OAuth1Session(API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
    # タイムライン取得エンドポイント
    url = "https://api.twitter.com/1.1/statuses/user_timeline.json"
    # パラメータ
    params = {
        "count": 1,
        "screen_name": screen_name,
        "include_entities": True,
        "exclude_replies": False,
        "include_rts": False,
    }

    # レスポンスからタイムラインリストを取得
    res = twitter.get(url, params=params)

    if res.status_code == 200:
        return json.loads(res.text)
    else:
        return None

3.ツイート内容から画像有無を判定

まず2で保存したJSONファイルを以下のクラスにします。

class Tweet:
    def __init__(self, json_file):
        self.created_at = json_file[0]["created_at"]
        self.tweet_id = json_file[0]["id"]
        self.text = json_file[0]["text"]
        self.user_name = json_file[0]["user"]["name"]
        self.user_screen_name = json_file[0]["user"]["screen_name"]
        self.user_mention = json_file[0]["entities"]["user_mentions"]
        self.image_urls_list = []

        # 添付ファイルがある場合
        if "extended_entities" in json_file[0]:
            self.media_number = len(json_file[0]["extended_entities"]["media"])
            self.content_type = json_file[0]["extended_entities"]["media"][0]["type"]

            for i in range(0, self.media_number, 1):
                self.image_urls_list.append(
                    json_file[0]["extended_entities"]["media"][i]["media_url"]
                )

        else:
            self.media_number = 0
            self.content_type = ""

self.media_number = len(json_file[0]["extended_entities"]["media"])を見て
画像が投稿されているかを見分けます。

is_content_type
def is_content_type(obj_tweet, expect_type):
    if obj_tweet.content_type == expect_type:
        return True
    else:
        return False

4.画像があるものをいいね&リツイート

画像が投稿されていた場合、以下のようにAPIをたたいていいねとリツイートを行います。
いずれもツイートIDを指定するだけでいいです。

push_favorite
def push_favorite(tweet_id):
    # 認証
    twitter = OAuth1Session(API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

    # リクエスト
    url = "https://api.twitter.com/1.1/favorites/create.json"
    params = {"id": tweet_id}
    req = twitter.post(url, params=params)
    req_json = json.loads(req.text)

    if req.status_code == 200:
        return True
    # すでにいいね済の場合
    elif req.status_code == 403 and req_json["errors"][0]["code"] == 139:
        return True
    else:
        return False
retweet
def retweet(tweetId):
    twitter = OAuth1Session(API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
    url = "https://api.twitter.com/1.1/statuses/retweet/%d.json" % tweetId
    res = twitter.post(url)
    res_json = json.loads(res.text)

    if res.status_code == 200:
        return True
    # すでにリツイート済
    elif res.status_code == 403 and res_json["errors"][0]["code"] == 327:
        return True
    else:
        return False