読者です 読者をやめる 読者になる 読者になる

StatsBeginner: 初学者の統計学習ノート

初学者が統計学、機械学習、R、Pythonの勉強の過程をメモっていくノート。

Python作業メモ: 残しておくとマズそうな自分のツイートをまとめて削除する(YouTubeリンク編)

著作権侵害にあたるYouTube動画へのリンクを削除する

 たまにツイッターで、YouTubeのリンクを貼り付けたツイートをしていますが、よく考えたら違法アップロードに該当するものを拡散してしまっている可能性があります。可能性とかいう曖昧なレベルで考えるのが面倒なので、いっそのことYouTubeのリンクを共有した過去のツイートをいっぺんに削除してしまおうと思いました。


 ついでに、人の悪口を言ってるようなツイートも削除して、自分のアカウントを「とてもいい人のアカウント」に変貌させていこうかとも思い出しましたが、まだ手法が検討できていません。(私の場合は必要性が低いですが、最近の就活生などには必要かも?)
 ツイートの感情分析を行って、負の感情の高ぶりが感じられるツイートを自動削除していけばいいんでしょうかね。本文を形態素解析で単語に分けて、人名を含むツイートを抽出した上で、さらに単語ごとに感情のポジ/ネガ度合いを定義した辞書*1*2を使って評価するようなことはできると思いますが、誹謗中傷・罵詈雑言のようなものを特定することってできるんでしょうかね。よくわからないのでそれは後回しにし、今日はYouTubeのリンクが入ってるツイートを削除するという、一瞬で終わる作業だけやりました。


 ところで、TwitterのAPIから自分のツイートを全件調べようとしても無理です。APIでツイートをまとめて取得する系の機能では、過去3000件分しか情報が取れないからです(ツイートidを個別に指定して、もっと古いツイートを参照したり操作したりすることはできる)。なので、Twitterが公式に提供している「全ツイート履歴ダウンロード」の機能を使えばいいと思います。まず全件履歴から該当するツイートのidを取得して、その後にAPIからid指定で消すわけです。


f:id:midnightseminar:20170504122227p:plain


 ダウンロードしたzipファイルを解凍するとフォルダになってるのですが、その中の'data/js/weets/'という場所に'2017_05.js'というようなファイル名で、月ごとのツイートがJavaScriptで保存されています。中身をみると、

Grailbird.data.tweets_2017_05 =
[{
  1件目のツイートデータ
}, {
  2件目のツイートデータ
}, {
  3件目のツイートデータ
}]


 というような感じで、配列の中にツイートのjsonが埋め込まれたような内容になっています。
 最初はこれを使おうと思ったのですが、よく見たら解凍後のフォルダの直下に'tweets.csv'というファイルも入っていて、上記のjsファイルよりも情報量は少ないのですが、ツイートのID、本文、リンク、retweetとreply関係の情報が含まれており、今回の目的には十分だったので、そっちを使うことにしました。

該当ツイートの抽出方法

 私の場合、YouTubeのリンクを含むツイートは3通りの経路で投稿しています。

  1. MacまたはiPhoneのSafariから、[↑]マークの共有ボタンでツイートする。
  2. YouTube側のツイッター連携機能でツイートする。
  3. YouTubeの動画ページをはてブに登録する際に、はてブの機能でブクマをツイートする。


 1つ目の方法だと、ツイート内に"https://www.youtube.com/watch?v=なんたらかんたら"とか"https://m.youtube.com/watch?v=なんたらかんたら"というURLが含まれます。(本文の見た目上はhttps://wwwなどは省略されますが、リンク先情報として入っている。)
f:id:midnightseminar:20170504122305p:plain


 2つ目の方法だと、"https://youtu.be/なんたらかんたら"という短縮URLが含まれます。
f:id:midnightseminar:20170504122411p:plain


 3つ目の方法だと、"http://htn.to/なんたらかんたら"という短縮URLが含まれますが、これははてブが生成するものなので、YouTube動画以外のリンクも同じ形式になります。
f:id:midnightseminar:20170504122421p:plain


 1つ目の場合は、リンクのところに"youtube.com"が含まれるツイートを検索すればOKです。
 2つ目の場合は、同じく"youtu.be"が含まれるツイートを見つければいいです。
 3つ目の場合は、htn形式のURLを探すと関係ないものも含まれてしまいます。ツイート本文に"動画タイトル - YouTube"という文字列が含まれる場合がほとんどなので、この文字列を探すことにします。
 例外があるかもしれませんが、これでほぼカバーできるでしょう。
 いずれも本文のデータを参照すれば見つかる気がしますが、今回はURLについてはexpanded_urlsというフィールドを見ることにしました。

Pythonでの作業

 以下、作業内容です。

import pandas as pd
import csv
import tweepy


# csvをpandasに読み込み
tw_df = pd.read_csv('解凍後フォルダ/tweets.csv', encoding='utf-8')


# 条件に合致する行を抽出し、ツイートID、本文、リンク先URLのフィールドだけ取得。
yt_df = tw_df.ix[\
      (tw_df['text'].str.contains(' - YouTube'))\
    | (tw_df['expanded_urls'].str.contains('youtube\.com'))\
    | (tw_df['expanded_urls'].str.contains('youtu\.be'))\
    , ['tweet_id', 'text', 'expanded_urls']]


# あとで念のため目視確認用に、抽出したツイートのcsvを出力しようと思っており、
# 改行コードが含まれていると何かをミスりそうなので半角スペースに置き換える。
# pandasの要素を直接書き換える方法がよくわからなかったので、textのフィールド
# をリストとして取り出して、そのリストを使ったデータフレームを新たに作った・・・
text_list = list(yt_df['text'])
for i in range(len(text_list)):
    text_list[i] = text_list[i].replace('\n', ' ')
yt_df = pd.DataFrame({'tweet_id':yt_df['tweet_id'],
                      'text':text_list,
                      'expanded_urls':yt_df['expanded_urls'],
                     },
                     columns=['tweet_id', 'text', 'expanded_urls']
                    )


# 確認用にcsvを出力
yt_df.to_csv('~/Desktop/yt.csv', index=None, encoding='utf-8', quoting=csv.QUOTE_NONNUMERIC)


# 削除すべきツイートのidリスト
rem_ids = list(yt_df['tweet_id'])


# 削除の処理はAPIで自分のアカウントを操作して行います。
# 件数があまりにも多い場合、リクエスト制限にひっかかります。


# APIハンドラインスタンスの生成
CONSUMER_KEY = '自分のコンシューマキー'
CONSUMER_SECRET = '自分のコンシューマシークレット'
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
ACCESS_TOKEN = '自分のアクセストークン'
ACCESS_SECRET = '自分のアクセスシークレット'
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)
api = tweepy.API(auth)


# 削除します。
# 試しにやってみてる時に何件か削除してしまい、どれを削除したか
# わからなくなったので、try-exceptで飛ばすことにしました・・・
for id in rem_ids:
    try:
        api.destroy_status(id)
    except:
        print('couln\'t delete id:' + str(id))
        continue


 pandasのto_csvでcsvを出力する時、引用符を付けるかどうかは、quotingという引数にPythonの標準モジュールcsvのプロパティを与えれば良いです。数値以外の情報に引用符をつけるなら'csv.QUOTE_NONNUMERIC'、全部に引用符を付けるなら'csv.QUOTE_ALL'、付けないなら'csv.QUOTE_NONE'といった具合。


 べつに著作権の侵害に当たらないような動画リンクも多いわけで、私の場合上記の条件で抽出した結果は220件程度(ツイート総数は1万3000件ぐらいです)だったので、目視確認用に出力したCSVをExcelなどで表示して、手作業で安全なやつを削除対象から除くことはできたと思います。しかし過去のツイートに特に未練はないので全部削除としました。

黒歴史の抹消について

 動画のリンクに限らず、残しておくと都合の悪いツイートを一気に消すという作業は、一部の就活生などには需要があるかもしれません。

  • 著作権侵害
  • 誹謗中傷、差別的言動
  • 政治的発言
  • 極度の下ネタ
  • 機密情報
  • 違法行為の告白(未成年の飲酒など)
  • 他人のプライバシー情報(顔写真なども)
  • 自分のプライバシー情報


 など、つい投稿してしまったけど消したいつぶやきはけっこうあるかもしれません。これらは件数が少なければ、根性で洗っていけば手作業で消すことはできるでしょう。また考え方として、古いツイートを残しておいてもとくにメリットはない場合が多いと思うので、一定期間経過したツイートはすべて消すという考え方もありなような気がします。


 しかしTwitterのデータは色々なサイトが勝手に収集して保存しているので、全部に削除依頼を出すのは大変です。というか無理。
 ネット上では、黒歴史的なものを完全に消し去ることはできないのだと覚悟を決めて、匿名管理を徹底するか、上品なつぶやきを心がけるかしたほうがいいですね。