Googleアカウントの保存ポリシー変更の件、みなさんいかがされていますか?
Google ストレージの仕組みに関する今後の変更 - Gmail ヘルプ
Google Oneも契約しているので容量には余裕があるのですが、GMailには二度どころか一度も読むことのないようなメールが山と溜まっています。年末にもなりましたし掃除でもするかとポチポチ消しはじめ、 楽○さんやY○hooさんが熱心にお勧めしてくださっている人生を豊かにするサービスや商品に関するメールを心苦しながら読まぬうちに削除し、 Promotionカテゴリ下に28,000件あった未読メールのうち、14,000件まで減りましたが、 はて、それでも14,000件ある…残りがどこから来たのか気になったので分析することにしました。
GMail削除UI改善のお知らせ
これまでGMailの検索結果の「全部選択」はリスト表示されているページのメールだけがまとめて選択できたのはご存知でしょうか?本日付で試してみたところ「全部選択」後に選択範囲を「検索結果全体に拡張」できるようになっていたので、まとめて削除が大変捗るようになっています。
Work Package
- GMail APIでメールリストを取得
- Pandasで前処理
- グラフ化
環境
- Python 3.7
- Windows 10
- Scoop
- wget
GMail APIでメールリストを取得
準備
Python Quickstart | Gmail API | Google Developersに従って何も迷うことはありません。 APIを有効化し、Desktopアプリ用のcredential.jsonを取得します。これはPythonコードと同じディレクトリに置きましょう。
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
wget https://raw.githubusercontent.com/googleworkspace/python-samples/master/gmail/quickstart/quickstart.py
python quickstart.py
スクリプト実行の際、ブラウザが開いて認証をするとtoken.pickleが保存され、以降のアクセスではこれを使うことができるようになります。
メールリスト取得
コードの全体はこちら⇒Fetch GMail List
メールのリストを取得してmessage.jsonというファイルに保存します。
メールIDの取得
messages().listのAPIでは、GMail内部で割り振られたメールIDを取得できます。
広告に分類されたメールを引っこ抜きます。リファレンスではlistでは好きな件数だけ情報を引き抜けるような事になっているようですが、実態としては1回のリクエストで500件までのようです。
try:
maxResults = 500
request = service.users().messages().list(userId='me', labelIds=['CATEGORY_PROMOTIONS'], maxResults=maxResults)
while request is not None:
results = request.execute()
consumed_token += 5
messages = results.get('messages', [])
db += messages
request = service.users().messages().list_next(request, results)
finally:
df = pd.DataFrame(db)
df['from'] = pd.Series(dtype='string')
df['subject'] = pd.Series(dtype='string')
df['timestamp'] = pd.Series(dtype='string')
df.to_json('messages.json', orient='records')
メールヘッダー情報の取得: 'From', 'Subject', 'Date'
APIを叩ける回数を調べると1秒間に50件のメール情報まで引き抜けるようでしたので、ちょっとSleepさせてます。(Usage limits | Gmail API | Google Developers)
try:
for i in tqdm.tqdm(df.index):
if not pd.isnull(df['from'][i]):
# Skip fetched data
continue
result = service.users().messages().get(userId='me', id=df['id'][i], format='metadata',
metadataHeaders=['From','Subject','Date']).execute()
consumed_token += 5
body = result.get('payload',[])
if not body:
print("Token Limit per minutes may be reached")
break
for el in body['headers']:
if el['name'] == 'From':
df.loc[i, 'from'] = el['value']
elif el['name'] == 'Subject':
df.loc[i,'subject'] = el['value']
elif el['name'] == 'Date':
df.loc[i, 'timestamp'] = pd.Timestamp(el['value'])
time.sleep(1/40)
finally:
df.to_json('messages.json', orient='records')
print("Consumed Token {}".format(consumed_token))
Pandasで前処理
さて、ここから取得した情報をjupyter notebookで内容分析します。
import numpy as np
import seaborn as sns
import matplotlib.pylab as plt
from matplotlib.ticker import PercentFormatter
import pandas as pd
import re
df = pd.read_json('messages.json')
前処理
まず、From形式情報からemailアドレスを取り出します。
def domain(row):
m = re.search('\<(.*)\>', row)
if m is None:
return row
return m.group(1)
df['email'] = df['from'].apply(domain)
# HEAT MAPを作るときに使う変数
df['Year'] = df['timestamp'].apply(lambda x: x.strftime('%Y'))
df['Month'] = df['timestamp'].apply(lambda x: x.strftime('%m'))
メール送信者の集計
aggregations = {
'email': ['count']
}
grouped = df.groupby(['email']).agg(aggregations)
grouped.columns = ["_".join(x) for x in grouped.columns.ravel()]
grouped = grouped.sort_values('email_count', ascending=False).reset_index()
グラフ化
メール送信者のトップ20とメールボックスに占める割合を算出します
grouped["cumpercentage"] = grouped["email_count"].cumsum()/grouped["email_count"].sum()*100
fig, ax = plt.subplots()
ax.bar(grouped.email[0:20], grouped["email_count"][0:20], color="C0")
ax2 = ax.twinx()
ax2.plot(grouped.email[0:20], grouped["cumpercentage"][0:20], color="C1", marker="D", ms=7)
ax2.yaxis.set_major_formatter(PercentFormatter())
ax.tick_params(axis="y", colors="C0")
ax2.tick_params(axis="y", colors="C1")
for tick in ax.get_xticklabels():
tick.set_rotation(90)
plt.show()
ついでにどのくらい熱心にメールを下さっているのかチェック
p = pd.pivot_table(df[df['email']==grouped['email'][0]], values='id', columns=['Year'] , index=['Month'], aggfunc='count')
sns.heatmap(p, cmap=sns.light_palette("seagreen", as_cmap=True), linewidths=.5)
4年以上メールくれてる
まとめ
- トップ20のメール送信者を削除すれば50%くらいが削除できそう
- 読んでない広告メールは購読解除しよう
No comments:
Post a Comment