あみのろぐ

クソコードとゲームのことについて

TwitterのTLから画像だけを取得してみる

始めに

はい、というわけでね。

今回から適当に自分で作ったクソコードとかゲームについての話とかを書いていきたいと思います。

f:id:ima3no:20180207113816j:plain

前置きはさておき今回はタイトルの通りTwitter関連の話です。

よくぼくのタイムラインではよさそうな画像をたくさんリツイートしてくれるありがたい人がいるんですけども、保存が面倒なのでプログラムにしてみようと思いました。

使ったもの

調べていたところ何種類かライブラリがあったので今回は上記の物を使用

ソース

import tweepy
import re
import urllib
import os
import time

#ここには各種自分で取得したキーを入れる
consumer_key = ""
consumer_secret = ""
access_key = ""
access_secret = ""

#Oauthの認証を行う
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_key, access_secret)
api = tweepy.API(auth)

#一応ディレクトリに出力するために指定
#先頭に.を付けると.pyファイルを置いた直下にディレクトリが作られる
path = "./img/"

def Downloadimg(tweet_data,username):
    if not os.path.isdir(path): #imgディレクトリが無ければ作成
        os.mkdir(path)
    if not os.path.exists(path + username): #ユーザーIDごとにディレクトリを作成して画像を格納する
        os.mkdir(path + username)
    savename = tweet_data
    filename = re.sub(r'https?://[a-zA-Z0-9.-]*/[a-zA-Z0-9.-]*/',"",savename) #ファイルネームを取得 pbs.twimg.com/media/〇〇〇.jpgの〇〇〇のところ
    img = urllib.request.urlopen(savename).read()
    with open(path + username + "/" + filename, mode="wb") as f:
        f.write(img)
    print("保存しました:" + savename)
    tweet_data = ""

def DownloadVideo(tweet_data,username):
    if not os.path.exists(path + username):
        os.mkdir(path + username)
    url = tweet_data
    file_name = re.sub(r'https?://[a-zA-Z0-9.-]*/[a-zA-Z0-9.-]*/',"",url)
    res = urllib.request.urlopen(url).read()
    with open(file_name, 'wb') as f:
        f.write(res)
    print("保存しました:" + savename)
    tweet_data = ""

class MyStreamListener(tweepy.StreamListener):
    def on_connect(self):
        print("接続しました")
        return

    def on_disconnect(self, notice):
        print('切断されました:' + str(notice.code))
        return

    def on_status(self, status):
        print("ユーザーID:" + status.user.screen_name)
        try:
            if "extended_entities" in status._json:
                for jpg_data in status._json["extended_entities"]['media']:
                    print("画像がありました:" + jpg_data["media_url"])
                    tweet_data = jpg_data["media_url"] #URLを取得しておく
                    if "retweeted_status" in status._json: #もしもリツイートされたツイートであれは元のツイート主のIDを取得しておく
                        username = status._json["retweeted_status"]["user"]["screen_name"]
                    else: 
                        username = status.user.screen_name
                    Downloadimg(tweet_data,username)
            elif "extended_entities" not in status._json:
                print("画像が含まれていないツイートです")
            elif "video_info" in status._json:
                print("動画、またはgifファイルです。")
                tweet_data = urllib.parse.urlparse = status._json["extended_entities"]["media"][0]['video_info']["url"]
                print(tweet_data)
                username = status.user.screen_name
                DownloadVideo(tweet_data,username)
        except KeyError:
            print("keyerror")
            return True
        except UnicodeEncodeError:
            data = (status._json).encode('cp932', "ignore")
            encodedata = data.decode('cp932')
            print(encodedata)
            return True

    def on_error(self, status_code):
        if status_code == 420:
            print("エラーが発生しました:" + str(status_code))
            return False

    def on_limit(self, track):
        print("API制限のため切断されました")
        return True

    def disconnect(self,notice):
        print("接続が中断しました")
        return True

if __name__ == "__main__":
    myStreamListener = MyStreamListener()
    stream = tweepy.Stream(auth = api.auth, listener=MyStreamListener())
#基本的にwhileで回してエラーが出たら60秒待機して再び接続する
    while True:
        try:
            stream.userstream()
        except:
            time.sleep(60)
            stream = tweepy.Stream(auth = api.auth, listener=MyStreamListener())

実行例

画像が含まれるツイートがあった場合 f:id:ima3no:20180207150431p:plain

こんな感じにそのツイートを投稿した人のIDでディレクトリを作ってその中に格納する。 f:id:ima3no:20180207150617p:plain

上手くプログラムが動いた時のおれ f:id:ima3no:20180207153428j:plain

謎のエラーに苦しむおれ f:id:ima3no:20180207154340j:plain

反省と課題

  • Oauthの認証を実装してみる(今回はライブラリを用いたが仕組みを理解できたので次は自分でやってみる。
  • 取得するツイートによってたまにエラーが出てしまう 今後修正予定(やるとは言ってない
  • 取得漏れが起こる(データの判定が効率悪いので直したい
  • 動画やgifの保存への対応
  • 重複した画像も保存してしまう(この辺りは保存した後に画像認識で判別が出来そう

最後に

短い文章なのに結構時間かかって書いてしまったしおれは 次回は機械学習関連かゲームのこと書きます では

参考にしたサイト様

Tweepyドキュメント — tweepy 3.6.0 ドキュメント

TweepyでStreamingAPIを叩いたときのstatusオブジェクト - ぽよメモ