2010-08-04 35 views
48

Tôi có tệp .ics ở định dạng sau. Cách tốt nhất để phân tích cú pháp là gì? Tôi cần truy xuất Tóm tắt, Mô tả và Thời gian cho từng mục nhập.Phân tích tệp (ics/icalendar) bằng cách sử dụng 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 

Trả lời

1

Bốn năm sau đó và hiểu ICS định dạng một chút tốt hơn, nếu đó là những sự chỉ lĩnh vực tôi cần, tôi chỉ muốn sử dụng các phương pháp chuỗi mẹ đẻ:

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 

Lưu trữ dữ liệu và phân tích cú pháp datetime là trái như một bài tập cho người đọc (it's always UTC)

câu trả lời cũ dưới đây


Bạn có thể sử dụng một regex:

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

tôi chắc chắn rằng nó có thể là có thể bỏ qua những lời đầu tiên và cuối cùng, tôi chỉ không chắc chắn làm thế nào để làm điều đó với regex. Bạn có thể làm theo cách này mặc dù:

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

Không phát minh lại bánh xe! – Dirk

+0

@Dirk Tôi nghĩ rằng nó có lợi cho cộng đồng để có nhiều cách để làm việc. Ai biết được, có thể trong một số trường hợp trình phân tích cú pháp ics sẽ không hoạt động chính xác và câu trả lời của Wayne sẽ tiết kiệm được ngày của ai đó! –

+0

@Dirk chắc chắn không phát minh lại bánh xe, nhưng cũng không thêm bất cứ điều gì nhiều hơn bạn cần. Nếu bạn chỉ cần một vài lĩnh vực đơn giản, bạn không thực sự cần bất cứ điều gì nhiều hơn lib std. Nếu tôi đã làm nhiều hơn thế này, tôi có lẽ * sẽ * chỉ cần đi trước và cài đặt một thư viện mặc dù - đặc biệt là nếu tôi đã thực sự cố gắng để * tạo * cuộc hẹn. –

0

tôi muốn phân tích từng dòng và thực hiện tìm kiếm cụm từ của bạn, sau đó nhận được chỉ mục và trích xuất và X số nhân vật nữa (tuy nhiên nhiều bạn nghĩ rằng bạn' sẽ cần). Sau đó phân tích chuỗi nhỏ hơn nhiều để làm cho nó trở thành những gì bạn cần.

61

The icalendar package trông đẹp mắt.

Ví dụ, để viết một tập tin:

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, bạn sẽ có được tập tin này:

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 

Nhưng những gì nằm trong tập tin này?

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

Bạn có thể nhìn thấy nó một cách dễ dàng:

>>> 
VCALENDAR 
VEVENT 
>>> 

gì về phân tích các dữ liệu về các sự kiện:

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

Bây giờ bạn nhận được:

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

Tuy nhiên, có vẻ như trả về thời gian biểu như là thời gian biểu ngây thơ, mà không có một utcoffset. :( – kojiro

+6

@BradMontgomery Dường như gói icalendar đã thay đổi người bảo trì và phiên bản 3.0 có sẵn theo giấy phép BSD tại đây: https://github.com/collective/icalendar – mpdaugherty

+0

@mpdaugherty đây là tin tuyệt vời! Thật tuyệt khi thấy mã đó nhận được một số bảo trì :) –

15

Bạn có thể có thể cũng sử dụng vobject mô-đun cho việc này: http://pypi.python.org/pypi/vobject

Nếu bạn có một tập tin sample.ics bạn có thể đọc nội dung của nó như thế nào, như vậy:

# 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' sẽ phân tích cú pháp chỉ một sự kiện. Ví dụ về 'readComponents' –

Các vấn đề liên quan