GoogleカレンダーのエクスポートをCSVにする。

Android端末を使っている関係で、Googleカレンダーを使用してスケジュール管理しているわけですが、これをエクスポートするとiCalendar形式のファイルになります。
iCalendar形式はxmlでもCSVでもなくて、
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:<ちよすけのメールアドレス>
X-WR-TIMEZONE:Asia/Tokyo
BEGIN:VTIMEZONE
TZID:Asia/Tokyo
X-LIC-LOCATION:Asia/Tokyo
BEGIN:STANDARD
TZOFFSETFROM:+0900
TZOFFSETTO:+0900
こんな感じにフィールド名:値という形式になっています。

これを容易に扱えるようにするには、「何かと都合のいい」CSV(カンマ区切り形式)が便利ですから、ぜひとも変換したい。

そしてこういうテキストを扱うのに適しているのは、昔ならsedやawk、perlなどでしたが、pythonでやればオブジェクト指向的にぱっぱと処理できるではないか、と思ったのでやってみました。

python2でもpython3でもどちらでもいいんですが、新しいことをやるのにはpython3のほうがいいです。

そして、iCalendar形式をpythonで扱うためのライブラリがすでにありました。
PyPi(ぱいぱい)よりicsです。

===
Ics.py is a pythonic and easy iCalendar library. It’s goals are to read and write ics data in a developer friendly way.
===

Windowsのpython3ではpipが標準で同梱されているので、コマンドプロンプトまたはPowerShellを開いて
pip install ics
でインストールできます。

そこでIdleを起動してちょっといじってみました。
まず、Googleカレンダーからエクスポートしたスケジュールデータはzipファイルに入っていますから、これを解凍し、さらに利用しやすいように名前を変更します。ここではchiyo.icsにしました。
まずはカレントディレクトリを移動します。chiyo.icsは/Users/chiyoに置いてあるとします。

>>> import os
>>> os.getcwd()
'C:\\Program Files\\Python36'
>>> os.chdir('/Users/chiyo')
>>> os.getcwd()
'C:\\Users\\chiyo'

pythonではパス区切りに '/' も使えるんですね。
では早速chiyo.icsを読み込んでみます。

>>> import ics
>>> f = open('chiyo.ics', 'r')
>>> c=ics.Calendar(f.read())
Traceback (most recent call last):
  File "", line 1, in 
    c=ics.Calendar(f.read())
UnicodeDecodeError: 'cp932' codec can't decode byte 0x86 in position 770: illegal multibyte sequence
>>> f
<_io.TextIOWrapper name='chiyo.ics' mode='r' encoding='cp932'>
>>> f.encoding
'cp932'

エンコードが違いますと怒られました。なんでデフォルトのファイルエンコーディングがcp932なんですかね。Windowsシステムの設定を参照してるんでしょうけど…。
そこで、標準ライブラリのcodecsを使用します。

>>> import codecs
>>> f=codecs.open('chiyo.ics', 'r', 'utf-8')
>>> c=ics.Calendar(f.read())
>>> c
<Calendar with 1588 events>

読み込めました。

cはiCalendarのBEGIN:VEVENTからEND:VEVENTに囲まれたそれぞれのスケジュールデータを保持していて、引数で指定できます。

>>> c.events[5]
<Event '岡山出張' begin:2008-12-10T00:00:00+00:00 end:2008-12-12T00:00:00+00:00>
>>> 

という感じ。

表示されているのはSUMMARY、DTSTART、DTENDの3つのフィールドだけですが、フィールドには他にもLOCATION、DESCRIPTIONなどがあります。
これらはそれぞれ、Calendar.name、Calendar.begin、Calendar.end、Calendar.location、Calendar.descriptionになります。

なので、プログラムとしてはc.events[]の添字を1から最大数まで増やしながら、上記のそれぞれのメンバを書き出すだけになります。

>>> for i in range(1, 100):
 print (c.events[i].begin, c.events[i].end, c.events[i].name, c.events[i].location, c.events[i].description, sep=',')

2008-12-10T00:00:00+00:00,2008-12-12T00:00:00+00:00,岡山出張,,

実際にはこんな風にどんどん出力されます。
日付形式とかちょっとアレな感じですが、これで出力できそうです。エンコーディングの問題があったので、出力用のファイルもcodecs.open()で開きます。

>>> fout=codecs.open('chiyo.out', 'w', encoding='utf-8')
>>> for i in range(1, 1588):
 print (c.events[i].begin, c.events[i].end, c.events[i].name, c.events[i].location, c.events[i].description, sep=',', file=fout)
 
>>> 

これでファイル 'chiyo.out' に出力できました。

実際には、どうもエンコーディングの違うフィールドがあるようで、データの一部が文字化けしてたりしましたが、一応目的は達成できました。
この文字化けはもしかしたらAndroidで使ってるカレンダーツールが悪さしているかもしれません。ちょっと注意してみましょう。

もうちょっとicsをいじってみる。 に続く。

0 件のコメント:

コメントを投稿

Windowsでシンボリックリンクを試してみる。

きっかけは、1つのファイルを別の名前で起動したら違う動きになるようなスクリプトを書く、でした。  busybox なんかでは、同じ実行形式ファイルの名前を、lsにすればlsと同じ、cpとすればcpと同じ動作をするようにしてますが、Pythonスクリプトでそれと同じように argv...