質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1277閲覧

Pytho、mail本文を同一カラムに収めてCSVに変換

KenUchi

総合スコア1

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/04/21 15:24

前提・実現したいこと

日々の売上情報を定型メールで受信し、受信した内容を正規化した上でcsv出力したいと考えております。csvの項目はdate(日付)、title(タイトル)、body(本文)で出力する想定です。

以下参考)
■受信するメールイメージ
(メール受信日)
4/03
(件名)
A商店
(本文)
04月01日
ペン
04月02日
消しゴム

■出力したいcsvイメージ

datetitlebody
04/01A商店ペン
04/02A商店消しゴム

発生している問題・エラーメッセージ

csvに書き込んだ際、本文がdataカラムに食い込んでしまう。

datetitlebody
04/01A商店04月01日
ペン
04/02
消しゴム

該当のソースコード

Python

1import imaplib 2import email 3import dateutil.parser 4import base64 5 6import csv 7import requests 8from bs4 import BeautifulSoup 9 10import pandas as pd 11 12# ヘッダ作成 13HEADER = ['date', 'title', 'body'] 14 15# mail文章をデータソースとして定義 16def main(): 17 gmail = imaplib.IMAP4_SSL("imap.gmail.com") 18 gmail.login("xxxxxx@gmail.com","xxxxxx") 19 gmail.select('inbox') 20 typ, [data] = gmail.search(None, "(ALL)") 21 22 # CSVへの書き込み 23 with open('sales_data.csv', 'w', encoding='utf-8') as f: 24 25 writer = csv.writer(f) 26 writer.writerow(HEADER) 27 28 #取得したメール一覧の処理 29 for num in data.split(): 30 ### 各メールへの処理 ### 31 result, d = gmail.fetch(num, "(RFC822)") 32 raw_email = d[0][1] 33 34 #文字コード取得用 35 msg = email.message_from_string(raw_email.decode('iso-2022-jp')) 36 msg_encoding = email.header.decode_header(msg.get('Subject'))[0][1] or 'iso-2022-jp' 37 38 # 日付の処理 39 date = dateutil.parser.parse(msg.get('Date')).strftime("%Y/%m/%d %H:%M:%S") 40 41 # タイトルの処理 42 subject = email.header.decode_header(msg.get('Subject')) 43 title = "" 44 for sub in subject: 45 if isinstance(sub[0], bytes): 46 title += sub[0].decode(msg_encoding) 47 else: 48 title += sub[0] 49 50 # 本文の処理 51 body = "" 52 if msg.is_multipart(): 53 for payload in msg.get_payload(): 54 if payload.get_content_type() == "text/plain": 55 body = payload.get_payload() 56 if msg_encoding == 'utf-8': 57 body = base64.urlsafe_b64decode(body.encode('ASCII')).decode("utf-8") 58 else: 59 if msg.get_content_type() == "text/plain": 60 body = msg.get_payload() 61 if msg_encoding == 'utf-8': 62 body = base64.urlsafe_b64decode(body.encode('ASCII')).decode("utf-8") 63 64 row = [date, title, body] 65 writer.writerow(row) 66 67 gmail.close() 68 gmail.logout() 69 return(0) 70 71main()

試したこと

・メールデータをdfに変換し、method='ffill'で日付とタイトルの空白行を埋めてみる。→埋まらず、解消ならず。
せめて、本文が1レコード内に収まれば、aplitで分割して、別途正規化しようと考えていますが、食い込んで意図しないカラムに入ってしまうことが解消できません。

補足情報(FW/ツールのバージョンなど)

JupyterNotebook環境にて実施。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

下記にある確認点はありますが、一旦回答します。
本文がdateカラムに食い込む理由としては、本文がメールそのまま出力されているためです。(改行がそのまま出力されている)

対応案

取得したbodyをそのまま出力するのではなく、改行で分割した上で日付ごとに出力すれば可能です。
あくまでもイメージですが以下のような形でいけるかと思います。

python

1d = None 2b = [] 3for row in body.split(): 4 if d is None: 5 d = row 6 elif re.search(r'\d{2}月\d{2}日', row): 7 for bb in b: 8 writer.writerow([d, title, bb]) 9 b = [] 10 d = row 11 else: 12 b.append(row) 13for bb in b: 14 writer.writerow([d, title, bb])

確認

1点よくわからない点がありますので確認させてください。

csvに書き込んだ際、本文がdataカラムに食い込んでしまう。

と記載がありますが、ここの内容がサンプルのメールと合いません。
以下のように出力されるかと思います。(時間部分は適当です)

datetitlebody
2021/04/03 01:02:03A商店04月01日
ペン
04月02日
消しゴム

CSVをExcelで確認するとフォーマットは表示上変換されそうですが、1行目が4/1となっているのがきになります。
msg.get('Date') で取得しているので受信日になるかと思うのですが。

投稿2021/04/22 05:12

編集2021/04/22 12:17
yamap55

総合スコア1376

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KenUchi

2021/04/22 12:08

yamap55さん 回答ありがとうございます。非常に助かります。早速試してみます。 確認事項について回答します。 ご指摘いただいた通り、私が提示したサンプルが間違っております。 dateはメールの受信日が正しく、yamap55さんが出力イメージとして作成いただいた、表のように出力されます。
KenUchi

2021/04/22 12:36

イメージのものを使わせしていただき、無事に食い込みを防ぐことができました。回答いただき本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問