Twitter から香風智乃の画像を検索して保存する

[Tweepy](http://www.tweepy.org/) というPython用の Twitter API ライブラリを使って、Twitter からチノちゃんこと[ごちうさ](http://www.gochiusa.com/)の[香風智乃](http://www.gochiusa.com/contents/chara/chino.html)の画像を検索して保存するスクリプトを作成した。

## Twitter API の準備

[Twitter APIの使い方まとめ](https://syncer.jp/twitter-api-matome) を参照に、アプリケーションの登録および各種 Twitter API Key を取得する。

## Tweepyの準備

Tweepy のインストールは下記のコマンドでできる (pip の場合)。

```
$ pip install tweepy
```

Tweepy の使い方は、[Tweepy Documentation](http://docs.tweepy.org/en/v3.5.0/) に書いてある。

例えば、自分のタイムラインを取得して表示するためには、以下のようにする。

```.py
import tweepy

CONSUMER_KEY        = 'Your Consumer Key'
CONSUMER_SECRET     = 'Your Consumer Secret'
ACCESS_TOKEN_KEY    = 'Your Access Token'
ACCESS_TOKEN_SECRET = 'Your Access Token Secret'

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)

public_tweets = api.home_timeline()
for tweet in public_tweets:
    print tweet.text
```

## 画像の検索&取得

Tweepy でキーワード検索するには `API.search()` を使用すればよい。
検索結果から、画像のURLを取得するには以下のようにする。

```.py
search_result = api.search(q=term)
for result in search_result:
    if result.entities.has_key('media'):
        for media in result.entities['media']:
            print media['media_url']
```

最後に、取得した画像のURLから画像をダウンロードするのだが、
画像のURLの最後に `:orig` を付けると縮小されていない元画像が取得できる。
（参照: [Twitter の画像 URL に :orig をつけると元画像が取得できる（できない場合もある） - ヤルキデナイズド](http://uasi.hatenablog.com/entry/2014/08/27/100933)）

## 作成したスクリプト

```chino_image_downloader.py
# -*- coding: utf-8 -*-
import os
import tweepy
import urllib2

#= 画像の保存先ディレクトリ
IMAGES_DIR = './images/'

#= Twitter API Key の設定
CONSUMER_KEY        = os.environ.get('TWITTER_CONSUMER_KEY')
CONSUMER_SECRET     = os.environ.get('TWITTER_CONSUMER_SECRET')
ACCESS_TOKEN_KEY    = os.environ.get('TWITTER_ACCESS_TOKEN_KEY')
ACCESS_TOKEN_SECRET = os.environ.get('TWITTER_ACCESS_TOKEN_SECRET')

#= 検索キーワード
KEYWORDS = ['香風智乃', 'チノちゃん']

#= 検索オプション
RETURN_PAR_PAGE = 100
NUMBER_OF_PAGES = 10

class ChinoImageDownloader(object):
    def __init__(self):
        super(ChinoImageDownloader, self).__init__()
        self.set_twitter_api()
        self.media_url_list = []

    def run(self):
        for keyword in KEYWORDS:
            self.max_id = None
            for page in range(NUMBER_OF_PAGES):
                self.download_url_list = []
                self.search(keyword, RETURN_PAR_PAGE)
                for url in self.download_url_list:
                    print url
                    self.download(url)

    def set_twitter_api(self):
        try:
            auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
            auth.set_access_token(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET)
            self.api = tweepy.API(auth)
        except Exception as e:
            print "[-] Error: ", e
            self.api = None

    def search(self, term, rpp):
        try:
            if self.max_id:
                search_result = self.api.search(q=term, rpp=rpp, max_id=self.max_id)
            else:
                search_result = self.api.search(q=term, rpp=rpp)
            for result in search_result:
                if result.entities.has_key('media'):
                    for media in result.entities['media']:
                        url = media['media_url_https']
                        if url not in self.media_url_list:
                            self.media_url_list.append(url)
                            self.download_url_list.append(url)
            self.max_id = result.id
        except Exception as e:
            print "[-] Error: ", e

    def download(self, url):
        url_orig = '%s:orig' % url
        filename = url.split('/')[-1]
        savepath = IMAGES_DIR + filename
        try:
            response = urllib2.urlopen(url_orig)
            with open(savepath, "wb") as f:
                f.write(response.read())
        except Exception as e:
            print "[-] Error: ", e

def main():
    try:
        downloader = ChinoImageDownloader()
        downloader.run()
    except KeyboardInterrupt:
        pass

if __name__ == '__main__':
    main()
``` 

## 参考文献

- [TVアニメ「ご注文はうさぎですか？？」公式サイト](http://www.gochiusa.com/index.html)
- [Twitter APIの使い方まとめ](https://syncer.jp/twitter-api-matome)
- [Tweepy Documentation — tweepy 3.5.0 documentation](http://docs.tweepy.org/en/v3.5.0/)
- [Tweepyを使って、PythonでTwitterのAPIを超簡単に操作する - StatsBeginner: 初学者の統計学習ノート](http://statsbeginner.hatenablog.com/entry/2015/10/21/131717)
- [Python2.7でTwitterタイムラインの画像を自動収集してみる - Qiita](http://qiita.com/imenurok/items/78d25e892c6557d24810)
- [Twitter の画像 URL に :orig をつけると元画像が取得できる（できない場合もある） - ヤルキデナイズド](http://uasi.hatenablog.com/entry/2014/08/27/100933)