2010-08-04 28 views
48

Tengo un archivo .ics en el siguiente formato. ¿Cuál es la mejor manera de analizarlo? Necesito recuperar el Resumen, la Descripción y la Hora de cada una de las entradas.Archivos de análisis (ics/icalendar) usando 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 

Respuesta

1

Cuatro años más tarde y la comprensión de ICS formatear un poco mejor, si esos eran los únicos campos que necesitaba, sólo haría uso de los métodos de las cadenas nativas:

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 

Almacenamiento de los datos y analizar la fecha y hora se deja como ejercicio para el lector (it's always UTC)

vieja respuesta por debajo de


usted podría utilizar una expresión regular:

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

Estoy seguro de que puede ser posible omitir la primera y la última palabra, pero no estoy seguro de cómo hacerlo con expresiones regulares. Se podía hacerlo de esta manera sin embargo:

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

¡No reinvente la rueda! – Dirk

+0

@Dirk Creo que es beneficioso para la comunidad tener múltiples formas de hacer las cosas. Quién sabe, quizás en algún caso el analizador ics no funcione correctamente y la respuesta de Wayne salvará el día de alguien. –

+0

@Dirk definitivamente no reinventar la rueda, pero tampoco agregar nada más de lo que necesita. Si solo necesita un par de campos simples, realmente no necesita nada más que la biblioteca estándar. Si estuviera haciendo mucho más que esto, probablemente * simplemente * seguiría adelante e instalaría una biblioteca, especialmente si realmente estaba tratando de * crear * citas. –

0

me gustaría analizar la línea por línea y hacer una búsqueda de sus términos, a continuación, obtener el índice y el extracto que X y el número de caracteres más (sin embargo muchos piensan que usted' ll necesidad). Luego analiza esa cadena mucho más pequeña para que sea lo que necesitas.

61

The icalendar package se ve bien.

Por ejemplo, para escribir un archivo:

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, se obtiene este archivo:

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 

Pero lo que se encuentra en este archivo?

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

Se puede ver fácilmente:

>>> 
VCALENDAR 
VEVENT 
>>> 

¿Qué pasa con el análisis de los datos sobre los acontecimientos:

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

Ahora se obtiene:

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

Sin embargo, parece devolver las fechas como fechas de programación ingenuas, que no tienen utcoffset. :( – kojiro

+6

@BradMontgomery Parece que el paquete icalendar ha cambiado los mantenedores y la versión 3.0 está disponible bajo la licencia BSD aquí: https://github.com/collective/icalendar – mpdaugherty

+0

@mpdaugherty ¡Estas son noticias increíbles! Es bueno ver ese código obtener algo de mantenimiento :) –

15

que probablemente podría también use el vobject módulo para esto: http://pypi.python.org/pypi/vobject

Si usted tiene un archivo sample.ics se puede leer su contenido como, por lo que:

# 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' analizará solo un vente. Da un ejemplo de 'readComponents' –