1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Pythonでtwitterでいいねしたツイートにある画像を収集するプログラムを作ってみた

Last updated at Posted at 2020-12-23

この記事はAkatsuki Advent Calender 2020の23日目になります

はじめに

運用して2~3年経っているのですが記事にしておらず今回いい機会なのですることにしました。

まず事の経緯として
twitterを覗いていると収集したい画像が回ってくることがあります。
そこでいちいち右クリック->ダウンロード->パス指定は非常に面倒だしそういうツイートが連続で来たら?となるとやってられません。

そこで何かしらトリガーがあって自動でダウンロードしてくれないかなと。
それで閲覧する用のwebページがあれば完璧ではないかと。
そんな訳で収集欲と技術欲半々のなか作ることにしました。

今回は収集のところだけ。
(それpixivとかで良くない?とか思うかもしれないですが
自分の欲しいやつだけ閲覧できるものが欲しいんです・・・)

要件

・RTではなくいいねのツイートのみダウンロードすることに。
いいねだとクリック手順が1つ少ないので速攻次のツイートに移れる
・収集はレンタルサーバーか何かで行う
自宅に常時つけるPCはないので、収集タイミング時につけてないといけないのは利便性が悪い。
・実装当時はstreaming apiが生きていたのでそれでリアルタイムでいいねツイートを取得
-> なくなったのでrest apiで時間をおいて取得する方にしました。
・ツイート内容やURL、@ IDなどもwebページでの検索用として保存しておく

開発環境

レンタルサーバー
・さくらサーバー

言語
・python3.6

使用ライブラリ
・requests_outhlib
・mysql.connector

Twitter Devへの登録

https://developer.twitter.com/
こちらで登録を行っておき、認証を通せるようにしときます。

実装へ

ところどころ省略しています

1. セッションの生成

twitter developerにてappを作っておく。
そこでKey And Tokenのタブに認証に必要なKeyとTokenがあるのでコピーしておきます。

twitter_screenshot.png

requests_outhlibにてセッションを作る際は
以下のコードで先程のKeyとTokenを指定します。

twitter_session = OAuth1Session(consumerKey
        , consumerSecret
        , accessToken
        , accessSecret)

2. APIの結果取得

https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/get-favorites-list
今回使ういいねAPIについてはこちら

コードでは以下のように使用します

#APIのResources URLと渡すパラメータを指定
#パラメータは上のページに載っていますが今回は以下の2つをメインで使います
#screen_name:@で表記するid 本来はuser_idを指定するのが確実ですが、収集アカウントは変える予定ないのでこれで
#count:一度に取得するツイート数 (max:200)
request = twitter_session.get("https://api.twitter.com/1.1/favorites/list.json", params = {"screen_name":ID, "count":200})

#古いのツイートを取得したい場合 パラメータに以下を追加します
#tweet_idよりも前のツイートを取得するようになります。指定なしで最新のツイートからになります
"max_id":tweet_id

結果はjsonで返ってきます。
status_codeでエラーかどうか判別。request.textにjsonのデータが有るためjson.loadsでjsonに変換しておきます。

if request.status_code == 200:
    print("rest connect")
else:
    print("rest Error code%d", request.status_code)
return ""
tweets = json.loads(request.text)

またこれを実行する際も以下の制限に気をつける必要があります
75リクエスト/15分
・取得されるツイートの順番はいいねした順番ではなくいいね先のツイート日時が新しい順に取得されます
なので古いツイートを取得する場合は工夫する必要があります

3. jsonデータを元に画像を取得

先程取得したtweets変数にはツイートが配列が入っているためfor文で1つずつ処理が可能です

for tweet in tweets:
    #ツイートから情報を取得

    #ツイートのID 一番最後のtweet["id"]を上で説明したtwitter_session.getのmax_idに指定することで
    #次のリクエストで取得する結果がかぶることなく処理できます
    tweet["id"]
    #表示する名前 
    tweet["user"]["name"]
    #@id
    tweet["user"]["screen_name"]
    #画像一覧 (URL)
    tweet["extended_entities"]["media"]
    #ツイート文
    tweet["text"]
    #ツイートURLは以下の組み合わせで
    "https://twitter.com/"+tweet["user"]["screen_name"]+"/status/"+tweet["id_str"]

今回は画像一覧なので

    #画像一覧 (URL)
    image_list = tweet["extended_entities"]["media"]

これを使います。
これも配列としてやってくるのでfor文で処理します
色々と省略はしていますが基本的にこれでダウンロード後保存を繰り返しています。

for image in image_list:
    url = image["media_url"]
    img = urllib.request.urlopen(url, timeout = 5).read()
    f = open(path, 'wb')
    f.write(img)
    f.close()

流れとしては以下の通り
・セッション作成
・リミットまでgetリクエスト75回ループ
・取得ツイートの画像を取得
・取得ツイートの最後のツイートIDを保持してリクエスト時に渡す

もし古いツイートを取得する場合は定期的に全いいねを見ていくのが良いかと

4.レンタルサーバーでCRON設定

今回はリクエストが15分ごとに制限があるのでそれに合わせてCRONを設定します
スクリーンショット 2020-12-23 23.28.51.png

これでいいね自動収集化完了ですが
web上で閲覧・検索をするのであればDBにツイートの情報保存したりする必要があります。

最後に

この後、DBやwebページは適宜設定して閲覧はできたのですが、
正直ほとんど見てません。収集とプログラムが動いたのでそこができただけで満足しちゃいました。
とはいえ学習するための題材としてはなかなか良かったと思います。スクリプト言語全然触っていなかったのと
自動化への興味が湧いた一番の作品?だったので。

なお、現在収集できた枚数は
image.png
約 1 7 万 枚

いいねの回数は
image.png
1 5 万 い い ね
自分でもこの人イカれてますねと思いました。自分だけど・・・

もっと良いシステムを作るとするならば機械学習で収集する画像も自動化が一番いいのですが、一度やろうとしたところ
収集したい画像の判定がめちゃんこ難しくて諦めました。自分の好みを落とし込まないといけない難易度高い・・・
学習のための画像はあるんですけどね・・・・・

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?