【自作黒歴史クリーナー】Python2.7を使ってtwitterの30万件近いツイートを全てツイ消ししてみた

### 概要
黒歴史クリーナを利用して全ツイートを削除しようと思ったが30万件近くあるツイートを消すことはできないようなので、pythonを使って全ツイートを削除するツールを作成する。

### 環境

- macOS Big Sur 11.2.3
- Python: 2.7.16

### 事前準備

1. pythonのバージョンを確認
1. pipの確認と導入

macにインストールされているpythonのバージョンを確認する。
バージョンが古いが気にせずに進めていく。
```bash
$ python --version
Python 2.7.16
```

とりあえず使う予定のmoduleを入れていくが、pip自体を入れていなかった…
```bash
$ pip install twitter
-bash: pip: command not found
```

ということでpipの導入していく。

```bash
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py

$ python get-pip.py
ERROR: This script does not work on Python 2.7 The minimum supported Python version is 3.7. Please use https://bootstrap.pypa.io/pip/2.7/get-pip.py instead.
```

実行すると2.7の場合はこっちから取得しろとあるので、従って再取得して実行。
```bash
$ curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py

$ python get-pip.py
（略）
Successfully installed pip-20.3.4
```

pipが入ったのでtwitterモジュールを導入しようと思うが、パスが通っていない模様。
```bash
$ pip install python-twitter
-bash: pip: command not found
```
[参考記事](https://qiita.com/tom-u/items/134e2b8d4e11feea8e12)に従ってパスを通せばpipが使えるようになってるのでtwitterモジュールを導入する。
普段pythonを使う機会が少ないのでbash_profileには追記しない。

```bash
$ export PATH="$HOME/Library/Python/2.7/bin:$PATH"
$ pip install python-twitter
```

### 実行
実行は下記の記事を参考に行う。

- [Pythonでツイートを全部消す](https://qiita.com/kakinaguru_zo/items/18ba8d5e54844b7ebd67)
- [ツイート全件削除に挑んだ話](https://note.com/notexb/n/n675aea80352c)

ちなみに今回は３０万件近いツイートを消すわけだが、上記記事によると20万件のツイートを一気に削除した結果、凍結されてしまったらしい。そこで今回は１度にツイ消しするツイート数を定めて、小分けに削除する。

#### 削除対象のツイートIDリストを作成

##### tweet.js（ツイート情報）の確認
tweet.jsの中身を確認すると自分のツイート情報がjson形式で格納されている。
今回は各ツイートのid（ツイートID）さえ取得できれば、削除用APIにそれを投げるだけで削除できる。
```javascript
"tweet" : {
      "retweeted" : false,
      "source" : "",
      "entities" : {
        "hashtags" : [ ],
        "symbols" : [ ],
        "user_mentions" : [ ],
        "urls" : [ ]
      },
      "display_text_range" : [
        "0",
        "15"
      ],
      "favorite_count" : "0",
      "id_str" : "",
      "truncated" : false,
      "retweet_count" : "0",
      "id" : "",
      "created_at" : "",
      "favorited" : false,
      "full_text" : "ツイート内容が入ってるよ",
      "lang" : "ja"
    }
  },
```
ここでtweet.jsのデータ数を確認したら101166件しかなかったが、30万ツイートくらいあるとこのように分割されるようだ。
```bash
├── tweet-part1.js
└── tweet-part2.js
```

とりあえずtweet.jsの各ファイルの確認はできたので、各ファイル冒頭の「window.YTD.tweet.part0 =」を削除する。
tweet.js以外にも「tweet-part1.js」や「tweet-part2.js」も消す必要があるため、同様に削除。
```javascript
// tweet-part1.jsではしっかりとpart1となっている
window.YTD.tweet.part1 = [
  {
    "tweet" : {
      "retweeted" : false,
```

下準備は完了したので実際に下記プログラムでツイートIDを「tweet.js」や「tweet-part1.js」、「tweet-part2.js」から吐き出す。
```python
import json

def output_tweet_id(filename):
    with open(filename,'r') as f:
    	tj=json.load(f)
    	for tweet0 in tj:
    		tweet = tweet0['tweet']
    		print(tweet['id'])

output_tweet_id('tweet.js')
output_tweet_id('tweet-part1.js')
output_tweet_id('tweet-part2.js')
```
実際にプログラムを実行して、適当なファイルに出力しておく。
出力後に行数を確認したら30万近い行数になっていたのでツイートIDの取得は完了。
```bash
python output_tweet_id_list.py > tweet_id_list.txt
```

#### ツイート削除部分の作成

下記が実際に実行したコード。１度実行する10000件のツイートを削除することができる。
このプログラムをcronで毎時間定期実行することで、およそ30時間で30万件のツイート削除を行う。

```python
import twitter
import json
import time

api = twitter.Api(
    consumer_key        ='xxxxxx',
    consumer_secret     ='xxxxxx',
    access_token_key    ='xxxxxx',
    access_token_secret ='xxxxxx',
    sleep_on_rate_limit = False
)

DELETE_TWEET_NUM_LIMIT = 10000 # １度に削除するツイート数
TARGET_ID_LIST_FILENAME = '~/tweet_id_list.txt' # 削除対象のツイートIDを格納したファイル

def output_next_target_id_list(filename, rows):
    with open(filename, "w") as f:
    	for row in rows:
       		f.write(row)


with open(TARGET_ID_LIST_FILENAME, "r") as f:
	rows = f.readlines()

if len(rows) == 0:
	print('[EXIT] No target_id.')
	exit()

target_id_list      = rows[:DELETE_TWEET_NUM_LIMIT]
next_target_id_list = rows[DELETE_TWEET_NUM_LIMIT:]

# 今回削除したツイートIDを除いたIDリストを書き出す	
output_next_target_id_list(TARGET_ID_LIST_FILENAME, next_target_id_list)

# 削除したツイートIDを削除ログとして書き出す
output_next_target_id_list('~/log/execute_log_' + str(time.time()) + '.txt', target_id_list)

# 実際にツイート削除しているのは下記
for target_id in target_id_list:
	tweet_id = target_id.rstrip('\n')
	print(tweet_id)
	try:
	    api.DestroyStatus(tweet_id)
	except Exception as e:
	    print(e.args)
```

##### cron設定
あとはcronを用いて指定時間おきに削除スクリプトを実行するだけ。
```bash
$ crontab -e
$ 0 * * * * /usr/bin/python/Users/hoge/test/tweet_all_delete_script.py // 1時間おきに削除スクリプト実行
```

### まとめ
定期実行で１時間おきにツイートを１万件ずつ削除することで、無事におよそ３０万件のツイートを削除することができた。
参考記事によると、２０万件のツイートを一度に削除したことにより凍結されてしまうことがあるようだが、今回の方法であれば今の所は凍結は回避できているようだ。（実行から20日ほど経っていて凍結されていないので多分…）