Python

2010-08-04 7 views
48

ile dosyaları ayrıştırma (ics/icalendar) Aşağıdaki biçimde bir .ics dosyasına sahibim. Ayrıştırmanın en iyi yolu nedir? Girişlerin her biri için Özet, Açıklama ve Saati almam gerekiyor.Python

BEGIN:VCALENDAR 
X-LOTUS-CHARSET:UTF-8 
VERSION:2.0 
PRODID:-//Lotus Development Corporation//NONSGML Notes 8.0//EN 
METHOD:PUBLISH 
BEGIN:VTIMEZONE 
TZID:India 
BEGIN:STANDARD 
DTSTART:19500101T020000 
TZOFFSETFROM:+0530 
TZOFFSETTO:+0530 
END:STANDARD 
END:VTIMEZONE 
BEGIN:VEVENT 
DTSTART;TZID="India":20100615T111500 
DTEND;TZID="India":20100615T121500 
TRANSP:OPAQUE 
DTSTAMP:20100713T071035Z 
CLASS:PUBLIC 
DESCRIPTION:Emails\nDarlene\n Murphy\nDr. Ferri\n 

UID:12D3901F0AD9E83E65257743001F2C9A-Lotus_Notes_Generated 
X-LOTUS-UPDATE-SEQ:1 
X-LOTUS-UPDATE-WISL:$S:1;$L:1;$B:1;$R:1;$E:1;$W:1;$O:1;$M:1 
X-LOTUS-NOTESVERSION:2 
X-LOTUS-APPTTYPE:0 
X-LOTUS-CHILD_UID:12D3901F0AD9E83E65257743001F2C9A 
END:VEVENT 
BEGIN:VEVENT 
DTSTART;TZID="India":20100628T130000 
DTEND;TZID="India":20100628T133000 
TRANSP:OPAQUE 
DTSTAMP:20100628T055408Z 
CLASS:PUBLIC 
DESCRIPTION: 
SUMMARY:smart energy management 
LOCATION:8778/92050462 
UID:07F96A3F1C9547366525775000203D96-Lotus_Notes_Generated 
X-LOTUS-UPDATE-SEQ:1 
X-LOTUS-UPDATE-WISL:$S:1;$L:1;$B:1;$R:1;$E:1;$W:1;$O:1;$M:1 
X-LOTUS-NOTESVERSION:2 
X-LOTUS-NOTICETYPE:A 
X-LOTUS-APPTTYPE:3 
X-LOTUS-CHILD_UID:07F96A3F1C9547366525775000203D96 
END:VEVENT 
BEGIN:VEVENT 
DTSTART;TZID="India":20100629T110000 
DTEND;TZID="India":20100629T120000 
TRANSP:OPAQUE 
DTSTAMP:20100713T071037Z 
CLASS:PUBLIC 
SUMMARY:meeting 
UID:6011DDDD659E49D765257751001D2B4B-Lotus_Notes_Generated 
X-LOTUS-UPDATE-SEQ:1 
X-LOTUS-UPDATE-WISL:$S:1;$L:1;$B:1;$R:1;$E:1;$W:1;$O:1;$M:1 
X-LOTUS-NOTESVERSION:2 
X-LOTUS-APPTTYPE:0 
X-LOTUS-CHILD_UID:6011DDDD659E49D765257751001D2B4B 
END:VEVENT 

cevap

1

Dört yıl sonra ve bu ihtiyacım sadece alanlar olsaydı ICS Sadece yerli dize yöntemleri kullanmak istiyorum, biraz daha iyi biçimlendirmek anlama: Veri Depolama

import io 

# Probably not a valid .ics file, but we don't really care for the example 
# it works fine regardless 
file = io.StringIO(''' 
BEGIN:VCALENDAR 
X-LOTUS-CHARSET:UTF-8 
VERSION:2.0 
DESCRIPTION:Emails\nDarlene\n Murphy\nDr. Ferri\n 

SUMMARY:smart energy management 
LOCATION:8778/92050462 
DTSTART;TZID="India":20100629T110000 
DTEND;TZID="India":20100629T120000 
TRANSP:OPAQUE 
DTSTAMP:20100713T071037Z 
CLASS:PUBLIC 
SUMMARY:meeting 
UID:6011DDDD659E49D765257751001D2B4B-Lotus_Notes_Generated 
X-LOTUS-UPDATE-SEQ:1 
X-LOTUS-UPDATE-WISL:$S:1;$L:1;$B:1;$R:1;$E:1;$W:1;$O:1;$M:1 
X-LOTUS-NOTESVERSION:2 
X-LOTUS-APPTTYPE:0 
X-LOTUS-CHILD_UID:6011DDDD659E49D765257751001D2B4B 
END:VEVENT 
'''.strip()) 

parsing = False 
for line in file: 
    field, _, data = line.partition(':') 
    if field in ('SUMMARY', 'DESCRIPTION', 'DTSTAMP'): 
     parsing = True 
     print(field) 
     print('\t'+'\n\t'.join(data.split('\n'))) 
    elif parsing and not data: 
     print('\t'+'\n\t'.join(field.split('\n'))) 
    else: 
     parsing = False 

ve datetime ayrıştırma (it's always UTC)

eski cevabı

aşağıda okuyucuya alıştırma olarak bırakılmıştır

import re 
text = #your text 
print(re.search("SUMMARY:.*?:", text, re.DOTALL).group()) 
print(re.search("DESCRIPTION:.*?:", text, re.DOTALL).group()) 
print(re.search("DTSTAMP:.*:?", text, re.DOTALL).group()) 

Ben ilk ve son sözlerini atlamak mümkün olabilir eminim, ben regex ile bunu nasıl emin değilim:


Bir düzenli ifade kullanabilirsiniz. Sen bunu gerçi bu şekilde yapabilirsiniz:

print(' '.join(re.search("SUMMARY:.*?:", text, re.DOTALL).group().replace(':', ' ').split()[1:-1]) 
+0

Tekerleği yeniden icat etmeyin! – Dirk

+0

@Dirk Bence toplumun işleri yapmanın birçok yoluna sahip olması faydalıdır. Kim bilir, belki de bazı durumlarda ics ayrıştırıcısı düzgün çalışmayacak ve Wayne'in cevabı birinin gününü kurtaracak! –

+0

@Dirk kesinlikle tekerleği yeniden icat etmiyor, aynı zamanda ihtiyacınız olandan fazlasını eklemiyor. Sadece birkaç basit alana ihtiyacınız varsa, gerçekten std lib'den daha fazlasına ihtiyacınız yoktur. Eğer bundan çok daha fazlasını yapıyor olsaydım, muhtemelen * sadece * devam edip bir kütüphane kurardım - özellikle de * randevular * yaratmaya çalışıyor olsaydım. –

0

ben satır satır ayrıştırmak ve terimler için bir arama yapın ve ardından indeksi almak ve bu ayıklamak ve daha fazla karakter X sayısı ediyorum (ancak birçok Eğer 'seni düşünüyorum ihtiyacım var). Sonra ihtiyacınız olan şeyi elde etmek için o kadar küçük ipi ayrıştırın.

61

The icalendar package güzel görünüyor.

Örneğin, bir dosyayı yazmak için:

from icalendar import Calendar, Event 
from datetime import datetime 
from pytz import UTC# timezone 

cal = Calendar() 
cal.add('prodid', '-//My calendar product//mxm.dk//') 
cal.add('version', '2.0') 

event = Event() 
event.add('summary', 'Python meeting about calendaring') 
event.add('dtstart', datetime(2005,4,4,8,0,0,tzinfo=UTC)) 
event.add('dtend', datetime(2005,4,4,10,0,0,tzinfo=UTC)) 
event.add('dtstamp', datetime(2005,4,4,0,10,0,tzinfo=UTC)) 
event['uid'] = '20050115T101010/[email protected]' 
event.add('priority', 5) 

cal.add_component(event) 

f = open('example.ics', 'wb') 
f.write(cal.to_ical()) 
f.close() 

tadaaa, bu dosyayı almak:

BEGIN:VCALENDAR 
PRODID:-//My calendar product//mxm.dk// 
VERSION:2.0 
BEGIN:VEVENT 
DTEND;VALUE=DATE:20050404T100000Z 
DTSTAMP;VALUE=DATE:20050404T001000Z 
DTSTART;VALUE=DATE:20050404T080000Z 
PRIORITY:5 
SUMMARY:Python meeting about calendaring 
UID:20050115T101010/[email protected] 
END:VEVENT 
END:VCALENDAR 

Ama ne bu dosyada yatıyor?

g = open('example.ics','rb') 
gcal = Calendar.from_ical(g.read()) 
for component in gcal.walk(): 
    print component.name 
g.close() 

Kolayca görebilirsiniz:

g = open('example.ics','rb') 
gcal = Calendar.from_ical(g.read()) 
for component in gcal.walk(): 
    if component.name == "VEVENT": 
     print(component.get('summary')) 
     print(component.get('dtstart')) 
     print(component.get('dtend')) 
     print(component.get('dtstamp')) 
g.close() 

Şimdi olsun: etkinliklerle ilgili verileri ayrıştırma konusunda ne

>>> 
VCALENDAR 
VEVENT 
>>> 

>>> 
Python meeting about calendaring 
20050404T080000Z 
20050404T100000Z 
20050404T001000Z 
>>> 
+1

Bununla birlikte, bu verileri, bir utcoffset olmayan naif datetimes olarak döndürüyor gibi görünüyor. :( – kojiro

+6

@BradMontgomery Bu icalendar paketinin bakımlarını değiştirmiş gibi görünüyor ve sürüm 3.0 burada BSD lisansı altında kullanılabilir: https://github.com/collective/icalendar – mpdaugherty

+0

@mpdaugherty bu harika bir haber! Bu kodu görmek güzel Yeni API (ve UTC işlemek için pytz) ile bazı bakım örnekleri :) –

15

Muhtemelen olabilir ayrıca'yi kullanın Bunun için 10 modülü: Bu yeni Python Package

# read the data from the file 
data = open("sample.ics").read() 

# parse the top-level event with vobject 
cal = vobject.readOne(data) 

# Get Summary 
print 'Summary: ', cal.vevent.summary.valueRepr() 
# Get Description 
print 'Description: ', cal.vevent.description.valueRepr() 

# Get Time 
print 'Time (as a datetime object): ', cal.vevent.dtstart.value 
print 'Time (as a string): ', cal.vevent.dtstart.valueRepr() 
+0

'readOne' yalnızca bir velayeti ayrıştırır. 'ReadComponents' örneğini verin –