Posted at

Pythonで黒歴史クリーナーを作ってみた。

More than 1 year has passed since last update.

Twitterやってる人なら一度は耳にした事があるであろう「黒歴史クリーナー

僕も黒歴史ツイートとか消し去りたいので作ってみました。

向き合わなきゃいけないのは分かってても、

消したい過去もある。


手順

プログラム実行する前にやる事があるので、まずは準備から。

前提として、Python3の実行環境が整っているものとします。

それ以外に、やらなきゃいけないのは以下です。


  • 各種キー情報の取得(参考記事)


    • Consumer Key (API Key)

    • Consumer Secret (API Secret)

    • Access Token

    • Access Token Secret



  • データ取得(参考記事)


    • 過去全てのツイートデータ



  • Pythonの外部ライブラリ取得


    • pip install pandas

    • pip install requests

    • pip install requests-oauthlib




実際のコード


deleteTweets.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""
# 実行コマンド
> python deleteTweets.py {
%Y} {%m} {%account_id}

#パラメータ説明
%Y: 処理終了年(未設定の場合は最初から最後までが対象)
%m: 処理終了月(未設定の場合は最初から最後までが対象)
%account_id: 対象アカウントID(特定の相手とのやりとりを消去したい場合に設定)
"""

import sys
import pandas as pd
from requests_oauthlib import OAuth1Session
from time import sleep

# 取得してきた各種キー情報を設定 ※※キー情報は他の人に教えちゃダメだよ!悪用されるよ!※※
twitter = OAuth1Session(
client_key="XXXXXXXXXX",
client_secret="XXXXXXXXXX",
resource_owner_key="XXXXXXXXXX",
resource_owner_secret="XXXXXXXXXX"
)

# ファイル食って、列['timestamp']をdatetime型にしておく
df = pd.read_csv("twieeted/tweets.csv")
df['timestamp'] = pd.to_datetime(df['timestamp'])

# 削除済みIDを読んで、DataFrameから消しておく
f = open("deleted_ids.txt")
deleted_ids = str(f.read()).split(",")
f.close()
print("started len(deleted_ids): {}".format(len(deleted_ids)))
for deleted_id in deleted_ids:
if "" != deleted_id:
df = df[df["tweet_id"] != int(deleted_id)]
deleted_ids = []

# 処理開始年月〜処理終了年月まで処理する
# - 処理終了年月が設定されてない場合は最後まで
start_y = int(min(df['timestamp']).strftime("%Y"))
start_m = int(min(df['timestamp']).strftime("%m"))
max_y = int(sys.argv[1]) if 2 <= len(sys.argv) else 0
max_m = int(sys.argv[2]) if 3 <= len(sys.argv) else 0
try:
while True:
# 処理対象年月のツイートのみに絞る(元オブジェクトに影響が及ばないように別オブジェクトに作成)
tweets = df[df["timestamp"].dt.year == start_y]
tweets = tweets[tweets["timestamp"].dt.month == start_m]
if len(tweets) <= 0:
print("bye:)")
break
print("processing... {}/{}".format(start_y, start_m))

"""
XXX ここは毎回変えないといけない。正規表現部分だけ外出しすればいいんだろうけど、面倒臭い。ごめん。
設定例:
先頭が"RT"で始まるツイート(=RT):
"^RT.*"
先頭が"RT"で始まらないツイート(=RT以外)
"^(?!RT).*"
先頭が"@"で始まるツイート(=リプライ)
"^@.*"
先頭が"@"で始まらないツイート(=リプライ以外)
"^(?!@).*"
"""

# 指定された正規表現に従って、ツイートを絞り込み
tweets = tweets[tweets["text"].str.contains("^(?!RT @).*$")] # 中の正規表現を変えて使ってね。ごめんね。
if 3 <= len(sys.argv):
tweets = tweets[tweets["text"].str.contains(sys.argv[3])]

# 1秒ごとにTwitterAPIを呼び出して削除する
# - 削除に失敗(!=200)の場合は、削除済みリストに入れないよう留意
# - すぐに削除せず、どういうツイートが取れるのか見たい時は、sleep以降をコメントアウトすると良い
if 0 < len(tweets):
for index, row in tweets.iterrows():
print("{} - {} : {}".format(row["timestamp"], row["tweet_id"], row["text"]))
sleep(1)
res = twitter.post("https://api.twitter.com/1.1/statuses/destroy/{}.json".format(int(row["tweet_id"])))
if res.status_code == 200 or res.status_code == 404:
deleted_ids.append(row["tweet_id"])
if res.status_code != 200:
print(" - [{}]: {}".format(res.status_code, res.json()))

# 処理終了年月になった場合はbye
if start_m == 12:
start_y += 1
start_m = 1
else:
start_m += 1
if start_y == max_y and start_m == max_m:
print("bye:)")
break

finally:
# 削除対象IDをファイルに書いて終了
# (元CSVをpandas.to_csv()で書き込んだら、データ型が変わってしまって再利用できなかったので苦肉の策。ごめん。)
print("finished len(deleted_ids): {}".format(len(deleted_ids)))
if 0 < len(deleted_ids):
f = open("deleted_ids.txt", "a")
f.write("{}".format(deleted_ids)
.replace("[", "")
.replace("]", "")
.replace("'", "")
.replace(" ", ""))
f.write(",")
f.close()


ソースコードコメント多くてすみません。

あれこれ手探りで、やっつけで作ったので、「何でこうしたの?」って部分が多くなったので、書いといた方が親切かなと思って書いてます。。。


というか、過去ツイートの黒歴史がうじゃうじゃ出てきて気持ち悪い...

いや、ツイートしたのは自分なんだけど。