Twitterで特定のユーザから画像を取得する

#はじめに
SLP KBIT Advent Calendar 2019の記事です。
前からtwitterでの画像収集などをやってみたいと思っていたので、この機会にやってみました。
今回のプログラムは特定のアカウントのツイートから画像をダウンロードするプログラムです。

###環境
Python3.7.5

###準備
今回twitterに上がっている画像を表示させるので、そのためのキーが必要になります。
キーの取得方法はググれば出てくるので割愛します。
tweepyを使うので、インストールしておきます。

```
pip install tweepy
```
取得したキーを入れるファイルを作ります。
実行ファイルと同じ場所でもいいですが、個人的にこのほうが良かったので・・・

```python:config.py
CONFIG1 = {
    "CONSUMER_KEY":"XXXXXXXXXXX",
    "CONSUMER_SECRET":"XXXXXXXXXXXX",
    "ACCESS_TOKEN":"XXXXXXXXXXXXXXXXXXX",
    "ACCESS_SECRET":"XXXXXXXXXXXXXXXXX",
   }
```
#画像取得
必要なものをインポートし、config.pyからキーを持ってきます。
下から3行はAPIを使うために必要です。

```python:twitter.py
import tweepy
from config import CONFIG
import urllib.request
import re


CONSUMER_KEY = CONFIG["CONSUMER_KEY"]
CONSUMER_SECRET = CONFIG["CONSUMER_SECRET"]
ACCESS_TOKEN = CONFIG["ACCESS_TOKEN"]
ACCESS_SECRET = CONFIG["ACCESS_SECRET"]

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)

api = tweepy.API(auth)
```

##プログラム全体
ターミナル上で動くプログラムで、IDを与えると、そのIDのアカウントからツイートを取得し、画像ツイートがあった場合、ダウンロードするものである。

```python:twitter.py
import tweepy
from config import CONFIG2
import urllib.request
import re


CONSUMER_KEY = CONFIG["CONSUMER_KEY"]
CONSUMER_SECRET = CONFIG["CONSUMER_SECRET"]
ACCESS_TOKEN = CONFIG["ACCESS_TOKEN"]
ACCESS_SECRET = CONFIG["ACCESS_SECRET"]

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)

api = tweepy.API(auth)

#キーワードで検索
def log(user_name, count, id):
    result_url = []
    for i in range(0, 2):
        results = api.user_timeline(screen_name=user_name, count=count, max_id=id)
        id = results[-1].id
        for result in results:
            if 'media' in result.entities:
                judg = 'RT @' in result.text
                if judg == False:
                    for media in result.extended_entities['media']:
                        result_url.append(media['media_url'])
    return result_url

def extract_pic_file(image_url):
    m = re.search(r"(([A-Za-z0-9]|_)+\.(png|jpg))", image_url)
    if m:
        name = 'img_dl/' + m.group(0)
    else:
        name = 'img_dl/None.png'

    return name

def save_image(url, name):
    count = 1
    for image_url in url:
        file_name = extract_pic_file(image_url)
        urllib.request.urlretrieve(image_url, file_name)
        count += 1

def fast(user_name):
    results = api.user_timeline(screen_name=user_name, count="1")
    for result in results:
        id = result.id
    return id

def start():
    count = 100
    user_name = input("IDを入力>>")
    id = fast(user_name)
    url = log(user_name, count, id - 1)
    save_image(url, user_name)

if __name__ == "__main__":
    start()
```
###流れ
log関数によってURLを取得し、save_image関数で指定したフォルダに画像を保存する。

###関数の説明
####log関数
アカウントID、取得ツイート数、ツイートIDを引数として受け取ります。
resultsをfor文で渡していきます。画像のURLはjsonのような形で格納されているので、それを取り出し、result_urlに格納します。それを返り値にします。
今回リツイートした画像は取得したくないので、if文で除外するようにしています。

####sava_image
名前の通り、画像を保存する関数になります。その際、URLでは保存するときにエラーが出るので、extract_pic_file関数を呼び出して、ファイル名を変換します。

####extract_pic_file関数
正規表現を用いて、画像のファイル名をURLから決めている。こうすることで、同じアカウントから画像を取得する際に、画像が被ることを防ぎます。

####fast関数
例外処理のための処理である。
これが必要な理由は、log関数はツイートのIDを引数として受け取り、そのツイートより過去のツイートを取得するようになっている。そのため、初めの例外処理が必要となる。

#終わりに
人にわかりやすく書くのは苦手ですね。
自分は関数の中で何が行われているかが書いていたほうが、わかりやすいと感じたので、関数ごとの説明を書きました。