Tweepyで過去ツイートを選択的に自動消去する方法

#はじめに
Twitter上の過去のPeing回答投稿を消したいと思いたったものの、消去対象が1000件近くあったので手動で消すのはあきらめ、代わりに自動で対象のツイートを消去してくれるスクリプトを書いてみました。

#Tweepyについて
[Tweepy](http://docs.tweepy.org/en/latest/)はTwitterのAPIを利用したPythonライブラリーです。これを使えばツイッターのbotを作ったり自動でいいねやフォローしたりすることができます。今回は特定のツイートを自動で消去するスクリプトを紹介します。

#準備
・Twitter APIの登録（[こちらを参考にしてみてください](https://qiita.com/kngsym2018/items/2524d21455aac111cdee)）
・Twitterアーカイブデータのダウンロード（[こちらを参考にしてみてください](https://help.twitter.com/en/managing-your-account/how-to-download-your-twitter-archive?&lang=en#)）
・Tweepy, pandasのインストール

#方針
Twitterアーカイブデータをダウンロードするとtweet.jsというファイルが一緒にダウンロードされて来ます。このファイルには下記のように過去のツイートデータが大量に入ってます。**"tweet" : {**　以降の全てが一つのツイートに関してのデータを示しており、これと同様のデータが無数に続いて一つのファイルとして構成されています。
方針としては、下記のtweet.jsファイルのうち、**"source" :**行に「https ://peing.net」が含まれているツイートを選択的に消去することを目指します。その際、個々のツイートに割り当てられているidも必要になるので**"id_str" :**行の数値データも抽出します。


```Javascript
 {
  "tweet" : {
    "retweeted" : false,
    "source" : "<a href=\"https://peing.net\" rel=\"nofollow\">Peing</a>",
    "entities" : {
      "hashtags" : [ {
        "text" : "Peing",
        "indices" : [ "18", "24" ]
      }, {
        "text" : "質問箱",
        "indices" : [ "25", "29" ]
      } ],
      "symbols" : [ ],
      "user_mentions" : [ ],
      "urls" : [ {
        "url" : "https://t.co/snIXxSjooH",
        "expanded_url" : "https://peing.net/ja/qs/636766292",
        "display_url" : "peing.net/ja/qs/636766292",
        "indices" : [ "30", "53" ]
      } ]
    },
    "display_text_range" : [ "0", "53" ],
    "favorite_count" : "0",
    "id_str" : "1203602228591788032",
    "truncated" : false,
    "retweet_count" : "0",
    "id" : "1203602228591788032",
    "possibly_sensitive" : false,
    "created_at" : "Sun Dec 08 09:08:27 +0000 2019",
    "favorited" : false,
    "full_text" : "ふっくらつやつやしたお米です。 \n\n#Peing #質問箱 https://t.co/snIXxSjooH",
    "lang" : "ja"
  }
```

#コード


###インポート
tweet.jsファイルから消去対象となるツイートデータの文字列を抽出する際に正規表現を利用するので**re**モジュールをインポートします。また抽出したデータからデータフレームを作るために**pandas**もインポートします。**datetime**は個人的に実行時間がどれくらいかを計測するためにインポートしているので必須ではありません。**tweepy**はもちろん必須です。

```python

import re
import pandas as pd
from datetime import datetime
import tweepy
```
###ツイートデータの抽出
tweet.jsから必要なデータ（**"source" :**, **"id_str" :**）を抽出し、データフレームとして出力する関数を定義します。

```python
def read_tweet_file(file):
    """
    reads a tweet.js into a pd.DataFrame
    """
    # tweet.jsファイルの読み込み
    with open(file) as dataFile:
        datalines = dataFile.readlines()
        # 抽出データを格納する空データフレームの作成
        colname = ['source', 'id']
        df = pd.DataFrame([], columns=colname)
        # 抽出する部分をリストに指定
        regexes = [r'    \"source\".*', r'    \"id_str\".*' ]
        for i, regex in enumerate(regexes):
            L = []
            for line in datalines:
                # 条件にマッチする部分を抽出
                match_obj = re.match(regex, line)
                if match_obj :
                    L.append(match_obj.group())
            # データフレームに格納
            df[colname[i]] = pd.Series(L)

        return df
```
###消去対象ツイートの抽出
データフレームから消去対象ツイートのIDを出力する関数を定義します。

```python
def extract_id(df):
    target_id = []
    for i in range(len(df)):
        # データフレームからpeingのツイートのみを抽出
        match_obj = re.search(r'https://peing.net', df['source'][i])
        if match_obj:
            # 消去対象ツイートIDをリストとして出力
            target_id.append(int(re.search(r'[0-9]+', df['id'][i]).group()))

    return target_id
```

###ツイートの消去
ツイートIDを指定し、当該ツイートを消去する出力する関数を定義します。

```python
def delete_tweets(target_id):
    delete_count = 0
    for status_id in target_id:
        try:
            # ツイートを消去
            api.destroy_status(status_id)
            print(status_id, 'deleted!')
            delete_count += 1
        except:
            print(status_id, 'deletion failed.')
    print(delete_count, 'tweets deleted.')
```

#実行
上記で定義した関数を実行します。

```python
# Twitter APIにアクセスするための認証
auth = tweepy.OAuthHandler('*API key*', '*API secret key*')
auth.set_access_token('*Access token*', '*Access token secret*')

api = tweepy.API(auth)
user = api.me()

# 実行
print(datetime.now())
df = read_tweet_file('tweet.js')
target_id = extract_id(df)
delete_tweets(target_id)
print(datetime.now())
```

#結果

976の対象ツイートを自動で消去することができました。
（実行時間10分程度）

```python
2020-02-07 17:24:57.816773
1204021701639426048 deleted!
1204020924015472640 deleted!
1204020044683833344 deleted!
1203904952684302337 deleted!

・・・（中略）・・・

1204025368052523014 deleted!
1204023316488560640 deleted!
1204023315221733376 deleted!
1204022282311499776 deleted!
976 tweets deleted.
2020-02-07 17:35:16.302221
```

# さいごに
ここで紹介したコードを自由にいじって充実したツイ消しライフを送りましょう。
お読みいただきありがとうございました。それでは！