twitterのいいねした画像を取得して保存するやつ作ってみた

#なぜ
元々IftttでTwitterでいいねした画像をGoogleDriveにアップロードするものを使っていたが、いつの間にか使えなくなっていたのでこの際リハビリがてら作ってしまおうという考え

#環境と使用履歴
・windows 10
・VScode←コードを書くときはたまに使う
・Heroku←全くわからない。はじめまして。
・Python←少し勉強した程度

#実装予定の動き
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/affbf4e9-075c-b06b-6966-8e58566348d2.png)

①Herokuから一定時間ごとにTwitter APIを使ってアクセスし、いいねの更新があった場合そのツイート画像を取得し、DBに画像idを記憶するする。

②Herokuからリストを元に画像をOneDriveにアップロードする

＊２回目以降はDBの画像idに取得したidがなければアップロードする

だいたいこんな感じ。
OneDriveにした理由はGoogleDriveの容量がほぼほぼなかったから
それ以上の理由はないのでもし、同じようなことをする場合はGoogleDriveなり自由に変えてもらって大丈夫だと思う。

#構築
とりあえずローカルでテストするためにimportするファイルをインストールする

```
pip install python-twitter
```
↑Twitter https://pypi.org/project/python-twitter/


```console
pip install microsoftgraph-python #使わなくなりました
```
~~↑OneDrive用 https://pypi.org/project/microsoftgraph-python/~~

```
pip3 install requests-oauthlib
```
↑OAuth1で認証するときに使うやつ https://pypi.org/project/requests-oauthlib/

```
<root>
├tmp                //画像の一時保存フォルダ
├main.py            //これから書き込んでいくファイル
├requirements.txt   //importするファイルの情報を書く
├runtime.txt        //pythonのバージョンを書く
└settings.yaml      //google driveの設定ファイル(後述)
```
現在の環境はこんな感じ

そしたら各ファイルを以下のように書き変えていきます

```python:main.py
import twitter #twitter
import microsoftgraph #onedrive
import json
import os
from requests_oauthlib import OAuth1Session #Oauth
import psycopg2 #SQL
import urllib.error
import urllib.request
import glob
import tempfile
from time import sleep 
```

```requirements.txt
python-3.7.6
```

```runtime.txt  
python-twitter==3.5
requests-oauthlib==1.3.0
microsoftgraph-python==0.1.7
psycopg2==2.8.5
```

今回はHerokuにGitHubからデプロイするのでGitHubにリポジトリを作成しましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/6f03e0a0-20e0-3de0-5e9e-3589c3884033.png)
作成したら`git status` `git push`しましょう
~~自分はここでSSH関係でエラー吐いて2時間くらいかかりました()~~
[GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~](https://qiita.com/shizuma/items/2b2f873a0034839e47ce)

そしたらHerokuのDeploy欄からGitHubを接続しておきましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/50371120-f469-9cd6-09e7-46fb898c211f.png)
#twitter
##いいねの取得
まずいいねを取得するところからやっていきましょう
エンドポイントは`https://api.twitter.com/1.1/favorites/list.json`を使っていきます。

```python:main.py
import twitter #twitter
import microsoftgraph #onedrive
import json
import os
from requests_oauthlib import OAuth1Session #Oauth
import psycopg2 #SQL
import urllib.error
import urllib.request
import glob
import tempfile
from time import sleep 

#後で環境変数に実装
consumer_key = '********'
consumer_secret = '********'
access_token = '********'
access_token_secret = '********'
#-------------------------------

CK = consumer_key
CS = consumer_secret
AT = access_token_key
ATS = access_token_secret
twitter = OAuth1Session(CK, CS, AT, ATS) #認証処理

#取得したいユーザーのidを入れる
user_id = "*********"

def get_favorites():
    url = "https://api.twitter.com/1.1/favorites/list.json"
    params = {'user_id' : user_id,'count' : 5} 
    res = twitter.get(url, params = params)

    if res.status_code == 200: 
        favorites = json.loads(res.text)
        for favorites_list in favorites:
            print(favorites_list)
            print('--------------------------------------------')

    else: #正常通信出来なかった場合
        print("Failed: %d" % res.status_code)


get_favorites()
```
とりあえず、これでいいねしたjsonファイルが取得できます。`params  = {'count' : }`を変更すると取得できるツイート数が増えます。
しかし、現在取得したデータはとても見づらいので整理していきます。


```python:main.py
#~~省略~~
    if res.status_code == 200: 
        favorites = json.loads(res.text)
        for favorites_list in favorites:
            print(favorites_list['user']['name']+'::'+favorites_list['text'])
            print(favorites_list['created_at'])
            print('--------------------------------------------')

```
```console:結果
tomoi🌧::取得テスト
Thu Apr 23 09:45:47 +0000 2020
--------------------------------------------
[{'id': 1253260454891159552, 'id_str': '1253260454891159552', 'indices': [9, 32], 'media_url': 'http://pbs.twimg.com/media/EWR5vmDVAAA2iU-.png', 'media_url_https': 'https://pbs.twimg.com/media/EWR5vmDVAAA2iU-.png', 'url': 'https://t.co/qiksxV3aN7', 'display_url': 'pic.twitter.com/qiksxV3aN7', 'expanded_url': 'https://twitter.com/_tomoi/status/1253260505541521408/photo/1', 'type': 'photo', 'sizes': {'large': {'w': 535, 'h': 713, 'resize': 'fit'}, 'medium': {'w': 535, 'h': 713, 'resize': 'fit'}, 'thumb': {'w': 150, 'h': 150, 'resize': 'crop'}, 'small': {'w': 510, 'h': 680, 'resize': 'fit'}}}]
```
いい感じに取得できてますね。


##画像URLの取得
ここまで来たらあとは簡単。jsonファイルからキー指定して取得していきましょう。

```python:main.py

#~~省略~~
def get_favorites():
    url = "https://api.twitter.com/1.1/favorites/list.json"
    params ={'user_id' : user_id,'count' : 7} 
    res = twitter.get(url, params = params)

    if res.status_code == 200: 
        favorites = json.loads(res.text)
        for favorites_list in favorites:
            print(favorites_list['user']['name']+'::'+favorites_list['text'])
            print(favorites_list['created_at'])
            print('--------------------------------------------')
            if  'media' in favorites_list['entities']:
                print('-------------true-------')
                print('--------------------------------------------')
                if 'photo' in favorites_list['entities']['media'][0]['type'] :
                    for media in favorites_list['extended_entities']['media']:
                        print(media['media_url'])
                        print('--------------------------------------------')
                    print('--------------------------------------------')
                else:
                    pass
    else: #正常通信出来なかった場合
        print("Failed: %d" % res.status_code)

get_favorites()
```

```console:結果
user_name::ツイート内容
Thu Apr 30 00:29:45 +0000 2020
--------------------------------------------
-------------true-------
--------------------------------------------
http://pbs.twimg.com/media/*************.jpg
--------------------------------------------
--------------------------------------------
```
画像のURLが取得できると思います
[詳しく知りたい方向け](https://qiita.com/tomoi/items/de9f06c95f0733e81a23)



##Herokuの環境変数
ベタ書きは危ないのでとっとと環境変数に入れておきましょう

```console;コンソール
heroku config:set TWITTER_CONSUMER_KEY='****************' --app "Herokuのアプリネーム"
heroku config:set TWITTER_CONSUMER_SECRET='****************' --app "Herokuのアプリネーム"
heroku config:set TWITTER_ACCESS_TOKEN_KEY='****************' --app "Herokuのアプリネーム"
heroku config:set TWITTER_ACCESS_TOKEN_SECRET='****************' --app "Herokuのアプリネーム"
heroku config:set TWITTER_USER_ID="****************" --app "Herokuのアプリネーム"
```
ここで全てに`twitter_`と付いているのは、OneDriveのtokenを設定する予定があるから


```python:main.py
#後で環境変数に実装
consumer_key = '********'
consumer_secret = '********'
access_token = '********'
access_token_secret = '********'
#-------------------------------

CK = consumer_key
CS = consumer_secret
AT = access_token_key
ATS = access_token_secret
twitter = OAuth1Session(CK, CS, AT, ATS) #認証処理

#取得したいユーザーのidを入れる
user_id = "*********"

↓

CK = os.environ["TWITTER_CONSUMER_KEY"]
CS = os.environ["TWITTER_CONSUMER_SECRET"]
AT = os.environ["TWITTER_ACCESS_TOKEN_KEY"]
ATS = os.environ["TWITTER_ACCESS_TOKEN_SECRET"]
twitter = OAuth1Session(CK, CS, AT, ATS)
user_id = os.environ["TWITTER_USER_ID"]

```

#DBの作成
~~[こちら](https://vavolab.com/article/2018/05/31/22/16/49/)の記事が見やすかったので参照して作成してください。~~
現在更新中なのか見れないため[こちら](https://webcache.googleusercontent.com/search?q=cache:8Yfb6UuGNF0J:https://vavolab.com/article/2018/05/31/22/16/49/+&cd=2&hl=ja&ct=clnk&gl=jp)から見てください。


##このままではDBを動かせない
Herokuのコマンドすら使えなのでPostgerをインストールしてください。
[PostgreSQLインストール](https://qiita.com/ucan-lab/items/fb74af3d78e71407db7b)
[PostgreSQL公式ドキュメント](https://www.postgresql.jp/)読める人はこっちのほうがいいかも

##DBにテーブルを作っていく
どのような構成にしたら便利か考えた結果↓のような構成にすることにしました。

Twitter_media_id　　画像の固有ID
DB-Posting_time　　DBに登録した時間
Twitter_Posting-time　　Twitterに投稿された時間
Twitter_URL　　画像のURL←この辺は使わないかも


```console
CREATE TABLE Twitter_media_id (Twitter_media_id TEXT,DB_Posting_time TIMESTAMP,Twitter_Posting_time TIMESTAMP,Twitter_URL TEXT);
```
＊Twitter_media_idという名前でカラムを作る際、テーブル名を決めておらず、脳死でテーブル名を決めていたらカラムと同名でテーブル名を作ってしまた()
取得してみるとちゃんと作成されていることがわかります。

```console:結果
***********::DATABASE=> SELECT * FROM twitter_media_id;
 twitter_media_id | db_posting_time | twitter_posting_time | twitter_url
------------------+-----------------+----------------------+-------------
(0 行)
```

```
ALTER TABLE twitter_media_id RENAME TO db;
```
テーブル名を変更したい場合は↑で変更してください
##DBと接続する&ファイルのダウンロード
接続するために```heroku pg:credentials:url --app "Herokuのアプリネーム"```を実行します。

```console:結果
Connection information for default credential.
Connection info string:
   "dbname=****** host=***-*-***-**-**.compute-*.amazonaws.com port=5432 user=********** password=********************** sslmode=********"     
Connection URL:
   postgres://**************:*********************************@***-*-***-**-**.compute-*.amazonaws.com:5432/********

```


```python:main.py
connection = psycopg2.connect("Connection URLで表示されたURL")#後で環境変数に追加する
cur = connection.cursor()
    
download_list =[]

def get_download_list():#ダウンロード済みのリストを取得する
    cur.execute("SELECT TWITTER_MEDIA_ID FROM DB;")
    for i in cur:
        download_list.append(str(i[0]))#tupleからstringに変換してlistに追加
        print(download_list)#[********,*********,*******]のように取得できる

def get_favorites():
    url = "https://api.twitter.com/1.1/favorites/list.json"
    params ={'user_id' : user_id,'count' : 7} 
    res = twitter.get(url, params = params)

    if res.status_code == 200: 
        favorites = json.loads(res.text)
        for favorites_list in favorites:
            print(favorites_list['user']['name']+'::'+favorites_list['text'])
            print(favorites_list['created_at'])
            print('--------------------------------------------')
            if 'media' in favorites_list['entities']:
                print('-------------true-------')
                i = 0
                print('--------------------------------------------')
                if 'photo' in favorites_list['entities']['media'][0]['type'] :
                    for media in favorites_list['extended_entities']['media']:
                        i += 1
                        download_file(media['media_url'],media['url'],i,favorites_list['created_at'])
                        print('--------------------------------------------')
                    print('--------------------------------------------')
                else:
                    pass
    else: #正常通信出来なかった場合
        print("Failed: %d" % res.status_code)

def download_file(url,path,number,t_post_time):
    try:
        with urllib.request.urlopen(url) as web_file:
            print(url)
            extension = url.split(".")[-1]
            print(number)
            Updated_path = path.split("/")[-1]
            file_path = Updated_path + "-" + str(number) + "." + extension#画像の名前兼固有IDの作成
            #ツイッターの短縮URLの後半(t.co/123456→123456) ＋ - ＋ 画像の枚数インデックス ＋ . ＋ 拡張子
            #123456-1.png
            i = SQL_Confirmation(file_path,t_post_time,url)
            if i == 0:#returnの値が0だった(SQLに登録されてない)場合に保存する
                urllib.request.urlretrieve(url,os.path.join("tmp",file_path))
                print("アップロード完了")
            else:
                pass
    except urllib.error.URLError as e:
        print(e)

def SQL_Confirmation(T_Media_ID,T_Posting_TIME,T_URL):#T_Media_ID：検索用
    if T_Media_ID not in download_list:#取得したリストにダウンロードしようとしているIDがあるか確認
        now_time = datetime.datetime.now()
        cur.execute("INSERT INTO DB (Twitter_media_id,DB_Posting_time,Twitter_Posting_time,Twitter_URL) VALUES (%s,%s,%s,%s)",[T_Media_ID,now_time,T_Posting_TIME,T_URL])#なかった場合DBに追加
        print("SQL true")
        return 0#リストに存在していなかったためダウンロードするようにする
    else:
        print("SQL false")
        return 1#リストに存在するためダウンロードしないようにする
        pass

def SQL_Close():#SQLの更新を保存する
    connection.commit()
    cur.close()
    connection.close()

get_favorites()
```
↑書いてて色々訂正する箇所が出てきたのでそのまま貼り付けてます。
プログラムの処理はコメントアウトに書いています。

#ここで急転
ここまで作ってきましたが、OneDriveにアップロードするのがとてもめんどくさいことがわかってきたので急遽GoogleDriveに変更します。

##pydriveのインストール
```
pip install pydrive
```
↑[pydrive](https://pypi.org/project/PyDrive/)

##Googleアカウント側の設定
ここはざっくりと説明していきます。
詳細は[こちらのサイト](https://note.nkmk.me/python-pydrive-download-upload-delete/)を参考に作成してください。

---
[https://console.developers.google.com/](https://console.developers.google.com/)から新規プロジェクトを作成してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/10b13a42-b0aa-9c1e-65b6-3fc3951a1b0c.png)

ダッシュボード(作成後に戻ってきた場合はAPIライブラリ)から「Google Drive API」を検索し、「APIとサービスの有効化」をする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/67585745-3c1f-0a5a-c88f-703c097eb6ad.png)

認証情報を作成してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/9c7e0596-65e1-7f0f-7552-4d052046eba8.png)

[外部]→アプリケーション名を適当につけて保存

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/65aa5ed8-caf2-15e5-17a6-135c9f04a349.png)

認証情報を作成から「OAuth クライアント ID の作成」で名前つけて作成しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/360f1748-251c-8a30-a17b-9e78402b7ed7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/9571b299-84f1-9264-82a8-49a6f73bdd42.png)

これでひとまず完成

#Google認証
ここから別のファイルを作成して認証していきます。
「write_text.py」と「settings.yaml」というファイルを作成して以下を記述してください。

```python:write_text.py
# 必要なライブラリのインポート
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
# OAuth認証を行う
gauth = GoogleAuth()
gauth.CommandLineAuth()
drive = GoogleDrive(gauth)
# テキストをGoogleドライブに書き込む
f = drive.CreateFile({'title': 'test.txt'})
f.SetContentString('賢い人に与えよ。彼はさらに賢くなる。')
f.Upload()
```

```yaml:settings.yaml
client_config_backend: settings
client_config:
  client_id: ★ここにOAuth クライアントID★
  client_secret: ★ここにクライアントシークレット★
save_credentials: True
save_credentials_backend: file
save_credentials_file: credentials.json
get_refresh_token: True
oauth_scope:
  - https://www.googleapis.com/auth/drive.file
  - https://www.googleapis.com/auth/drive.install
```

保存したら実行してください。するとURLが発行されるのでURLをブラウザに貼り付けて許可してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/edfe5f37-98da-bacb-42a4-39c8757d881d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/b009db00-36a8-1c55-0043-16c6c8df7f27.png)

許可すると認証コードが発行されるのでターミナルに戻り、貼り付けてEnterで実行してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/a413aa9e-1e6a-24ac-d078-dc70b98241d3.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/07eb7552-9a63-15a4-75a8-d4e93487c36b.png)

これでtextファイルが作成できるっぽい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/af2349d1-6c58-83fc-25d4-af70f16b3a6c.png)

#GoogleDriveの組み込み
```python:main.py
from pydrive.auth import GoogleAuth #GoogleDrive
from pydrive.drive import GoogleDrive

gauth = GoogleAuth()
gauth.CommandLineAuth()
drive = GoogleDrive(gauth)
print("googledrive setup")

def GoogleDrive_Upload(file_path):
    print(file_path)
    f = drive.CreateFile()
    print(type(f))
    f.SetContentFile(file_path)
    print("----------------")
    print(f)
    f['title'] = os.path.basename(file_path)
    print("----------------")
    print(f)
    print("Uploading...")
    f.Upload()
    print("Uploaded!")
    print("----------------")

```
``GoogleDrive_Upload()``で引数にファイルパスを指定するとGoogleDriveにアップロードできる。

#Heroku環境変数
```console
heroku config:set GOOGLE_CLIENT_SECRET='****************' --app "Herokuのアプリネーム"
heroku config:set GOOGLE_CLIENT_ID='****************' --app "Herokuのアプリネーム"
heroku config:set DB='****************' --app "Herokuのアプリネーム"
```
追加し終わったら``git push``してHerokuでデプロイしましょう。
※ここでpushするファイルは以下のものです。

```
<root>
├tmp                //画像を一時保存するフォルダ
|└.gitkeep          //これがないとからのフォルダをpushできない
├main.py            //これから書き込んでいくファイル
├requirements.txt   //importするファイルの情報を書く
├runtime.txt        //pythonのバージョンを書く
└settings.yaml      //google driveの設定ファイル
```
デプロイまで終わったらHerokuでもう一度Googleの認証をします。
Heroku→more→Run consoleから``python main.py``を実行しましょう

すると、URLが生成されるので認証してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/aab0b6b4-aedd-72f9-dc09-9873b1b98852.png)
🤔🤔🤔🤔
OAuth認証がエラー吐いた
すぐに出てきた考えはymlの環境変数の取得に失敗してること
と思ってローカル環境でidとsecretを削除して実行したらURLではなくエラーがしっかり出てきた。つまり環境変数の取得はできてそう。つまりOAuthがどこかで失敗してる。

正直精神的に死んできているので諦めて先ほど作成していた`credentials.json`ファイルを`git push`することにする。

#注意
今回は個人でしかもprivateリポジトリなので`credentials.json`をアップロードするという判断をしました。
基本的に**アクセストークンなどをベタ書きでネットにアップロードする**などの行為は**大変危険**です。推奨は一切しません。それでもやりたいという方は**自分で判断して**実行してください。**僕は一切責任を負いません。**

僕は、また気が向いたら直したいとおもいます。

#実行
実際に走らせてみるとしっかり動いてくれた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/e04e0f06-5e6c-2d7b-f992-c65788a2b10a.png)

あとは定期的に実行してくれれば良さそう。

#Heroku Scheduler
[参考元](https://hashikake.com/heroku-scheculer#toc8)
Resources→Add-onsから`Heroku Scheduler`を追加しましょう。

ちなみに追加する際にクレジットカードの登録が必須になっているらしいです。freeプランから変更しない限り課金はされないようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/18c6ddef-c9cf-26f0-290c-de9f04369ab7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/dbb0c573-e4e1-da75-8818-3a7b93f169dc.png)

追加できたら`Heroku Scheduler`を開き、`Create jpb`で以下のように設定していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/fb6dabc4-cf2d-310b-21a5-fa4baae25874.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/2a2797aa-ac51-2311-111a-aa5a963424c4.png)
毎日午前9時に`python main.py`を実行する設定になっています。
時刻はUTC基準になっているので [設定したい時間] - [9時間] = [入力する時間] になります。

#最終的なコード
```python:main.py
import twitter #twitter
import json
import os
from requests_oauthlib import OAuth1Session #Oauth
import psycopg2 #SQL

import urllib.error
import urllib.request
import glob
import tempfile
from time import sleep 
import datetime  

from pydrive.auth import GoogleAuth #GoogleDrive
from pydrive.drive import GoogleDrive

CK = os.environ["TWITTER_CONSUMER_KEY"]
CS = os.environ["TWITTER_CONSUMER_SECRET"]
AT = os.environ["TWITTER_ACCESS_TOKEN_KEY"]
ATS = os.environ["TWITTER_ACCESS_TOKEN_SECRET"]
twitter = OAuth1Session(CK, CS, AT, ATS)
user_id = os.environ["TWITTER_USER_ID"]

db = os.environ["DB"]

connection = psycopg2.connect(db)
cur = connection.cursor()

download_list =[]

path = os.getcwd()
print(path)
file = os.listdir(path)
print(file)

gauth = GoogleAuth()
gauth.CommandLineAuth()
drive = GoogleDrive(gauth)
print("googledrive setup")

def SQL_get_download_list():
    cur.execute("SELECT TWITTER_MEDIA_ID FROM DB;")
    for i in cur:
        download_list.append(str(i[0]))
    print(download_list)

def SQL_Confirmation(T_Media_ID,T_Posting_TIME,T_URL):#Twitter_media_id：検索用
    if T_Media_ID not in download_list:
        now_time = datetime.datetime.now()
        cur.execute("INSERT INTO DB (Twitter_media_id,DB_Posting_time,Twitter_Posting_time,Twitter_URL) VALUES (%s,%s,%s,%s)",[T_Media_ID,now_time,T_Posting_TIME,T_URL])
        print("SQL true")
        return 0
    else:
        print("SQL false")
        return 1
        pass

def SQL_Close():
    connection.commit()
    cur.close()
    connection.close()

def GoogleDrive_Upload(file_path):
    print(file_path)
    f = drive.CreateFile()
    print(type(f))
    f.SetContentFile(file_path)
    print("----------------")
    print(f)
    f['title'] = os.path.basename(file_path)
    print("----------------")
    print(f)
    print("Uploading...")
    f.Upload()
    print("Uploaded!")
    sleep(0.5)
    print("----------------")

def get_favorites():
    url = "https://api.twitter.com/1.1/favorites/list.json"
    params ={'user_id' : user_id,'count' : 200} 
    res = twitter.get(url, params = params)

    if res.status_code == 200: 
        favorites = json.loads(res.text)
        for favorites_list in favorites:
            print(favorites_list['user']['name']+'::'+favorites_list['text'])
            print(favorites_list['created_at'])
            print('--------------------------------------------')
            if 'media' in favorites_list['entities']:
                print('-------------true-------')
                i = 0
                print('--------------------------------------------')
                if 'photo' in favorites_list['entities']['media'][0]['type'] :
                    for media in favorites_list['extended_entities']['media']:
                        i += 1
                        download_file(media['media_url'],media['url'],i,favorites_list['created_at'])
                        print('--------------------------------------------')
                    print('**********************************')
                else:
                    pass
    else: #正常通信出来なかった場合
        print("Failed: %d" % res.status_code)


def download_file(url,path,number,t_post_time):
    try:
        with urllib.request.urlopen(url) as web_file:
            print(url)
            extension = url.split(".")[-1]
            print(number)
            _url = url + ":orig"
            Updated_path = path.split("/")[-1]
            file_path = Updated_path + "-" + str(number) + "." + extension
            i = SQL_Confirmation(file_path,t_post_time,url)
            if i == 0:
                urllib.request.urlretrieve(_url,os.path.join("tmp",file_path))
                GoogleDrive_Upload(os.path.join("tmp",file_path))
                print("アップロード完了")
            else:
                pass
    except urllib.error.URLError as e:
        print(e)


def main():
    SQL_get_download_list()
    get_favorites()
    SQL_Close()
    print("完了")

main()
```

```txt:requirements.txt
python-twitter==3.5
requests-oauthlib==1.3.0
PyDrive==1.3.1
psycopg2==2.8.5
google-api-python-client==1.7.11
google-auth==1.11.0
google-auth-httplib2==0.0.3
google-auth-oauthlib==0.4.1
```

```txt:runtime.txt
python-3.7.6
```

```yaml:settings.yaml
client_config_backend: settings
client_config:
  client_id: ${GOOGLE_CLIENT_ID}
  client_secret: ${GOOGLE_CLIENT_SECRET}
save_credentials: True
save_credentials_backend: file
save_credentials_file: credentials.json
get_refresh_token: True
oauth_scope:
  - https://www.googleapis.com/auth/drive.file
  - https://www.googleapis.com/auth/drive.install
```


#完走した感想
すごくダラダラと作ってしまったなという反省としっかり最後まで作りきった達成感が混ざってもやもやしてます。

改良する場所もすでに少しあって、GoogleDriveにアップロードする際にroot直下に保存しいるところを`Twitter`フォルダに入れておくことや、DBの最大保存数が10000件なので一定数以上保存されたら削除する処理を入れるなどやることがまだあって今は楽しいです。また、改良版ができたらgithubにでも上げてURL貼っておきます。

そして、HerokuのGoogle認証は本当に何もわからないのでなにか知っていることがあればコメントしてもらえると幸いです。

#追記(5/11)
##GoogleDriveの指定のフォルダにアップロード
フォルダのidを取得
アップロードしたいフォルダにアクセスしてURLの最後の部分をコピーする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/065175b3-a176-4f55-e476-72c81d36f7da.png)
↓

環境変数の追加
先程コピーしたidを環境変数に追加
```
heroku config:set FOLDER_ID='****************' --app "Herokuのアプリネーム"
```
↓コードの書き換え

```python:main.py
folder_id = os.environ["FOLDER_ID
"]
def GoogleDrive_Upload(file_path):
    f = drive.CreateFile({"parents": [{"id": folder_id}]})
    f.SetContentFile(file_path)
    f['title'] = os.path.basename(file_path)
    print("----------------")
    print(f)
    print("Uploading...")
    f.Upload()
    print("Uploaded!")
```

##DBの自動削除
```python:main.py
def SQL_Delete():
    cur.execute("SELECT count(*) FROM DB;")
    count = int(cur.fetchone()[0])
    print(count)
    if count >= 1000:
        cur.execute("DELETE FROM db WHERE twitter_posting_time IN (SELECT twitter_posting_time FROM db ORDER BY twitter_posting_time ASC LIMIT 500);")
        print("削除完了")
```

PostgreSQLでは`DELETE FROM db ORDER BY twitter_posting_time ASC LIMIT 5;`で実行できなので注意

#その他参考元
~~[python-OneDrive[microsoftgraph-python]](https://pypi.org/project/microsoftgraph-python/)~~
[python-twitter](https://pypi.org/project/twitter/)
[Twitter開発ドキュメント日本語訳](http://westplain.sakuraweb.com/translate/twitter/Documentation/REST-APIs/Public-API/REST-APIs.cgi)
[【GitHub】アプリのバージョン管理を行う](https://qiita.com/yukibe/items/067714d9adec6a6b69d8)
[PostgreSQL型一覧](https://thinkit.co.jp/cert/marugoto/2/1/19/2table.htm)
[Python, PyDriveでGoogle Driveのダウンロード、アップロード、削除など](https://note.nkmk.me/python-pydrive-download-upload-delete/)
[ゼロからはじめるPython 第16回 PythonからGoogleドライブを操作しよう(その1)](https://news.mynavi.jp/article/zeropython-16/)
[PyDrive OAuth](https://gsuitedevs.github.io/PyDrive/docs/build/html/oauth.html)