使用Pythonparsing文件(ics / icalendar)

我有以下格式的.ics文件。 什么是parsing它的最好方法? 我需要检索每个条目的摘要,描述和时间。

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 

icalendar包看起来不错。

例如,要写一个文件:

 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/27346262376@mxm.dk' event.add('priority', 5) cal.add_component(event) f = open('example.ics', 'wb') f.write(cal.to_ical()) f.close() 

Tadaaa,你得到这个文件:

 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/27346262376@mxm.dk END:VEVENT END:VCALENDAR 

但是这个文件里面有什么?

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

你可以很容易地看到它:

 >>> VCALENDAR VEVENT >>> 

parsing有关事件的数据怎么样:

 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() 

现在你得到:

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

你也可以使用vobject模块来实现: http : vobject

如果你有一个sample.ics文件,你可以阅读它的内容,如:

 # 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() 

你也可以使用这个新的Python包: http : //packages.python.org/pyICSParser/

它parsing文件并转换成Python数组以便于处理。

四年后,理解ICS格式好一点,如果那些是我需要的唯一的字段,我只是使用本地string方法:

 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 

存储数据和parsingdate时间留给读者(它总是UTC)

老答案在下面


你可以使用正则expression式:

 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() 

我敢肯定它可能会跳过第一个和最后一个单词,我只是不知道如何用正则expression式。 你可以这样做:

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

我会逐行parsing,并search你的条件,然后得到索引,并进一步提取和X个字符(无论你认为你需要多less)。 然后parsing这个更小的string,以得到它所需要的。