En un
artículo anterior, consideramos un enfoque para crear csv desde xml en una base de datos publicada por FIAS. El análisis se basó en el analizador DOM, que carga todo el archivo en la memoria antes del procesamiento, lo que llevó a la necesidad de dividir archivos grandes en vista de la cantidad limitada de RAM. Esta vez se propone ver qué tan bueno es el analizador SAX y comparar su velocidad con el analizador DOM. El más grande de los archivos de base de datos FIAS, casas, 27.5 GB de tamaño, se utilizará como sujeto de prueba.
Entrada
Nos vemos obligados a molestar de inmediato al público más respetado: de inmediato no se puede alimentar el analizador SAX, el archivo de base de datos de casas FIAS fallará. El analizador se bloquea con el error "no está bien formado (token no válido)". E inicialmente hubo sospechas de que el archivo de la base de datos estaba roto. Sin embargo, después de cortar la base de datos en varias partes pequeñas, se descubrió que las salidas fueron causadas por un cambio en la codificación de los números de casas y / o edificios. Es decir, las etiquetas STRUCNUM o HOUSENUM se encontraron con una letra escrita con una codificación extraña (no UTF-8 y ANSI, en la que se formó el documento):

Al mismo tiempo, si esta codificación se corrige ejecutando el archivo a través de la función remove_non_ascii, el registro toma la forma:

Tal archivo tampoco fue absorbido por el analizador, debido a caracteres adicionales.
Tenía que recordar expresiones regulares y limpiar el archivo antes de cargarlo en el analizador.
Pregunta: por qué es imposible crear una base de datos normal, que se presenta para el trabajo adquiere un tono retórico.
Para alinear las capacidades de inicio de los analizadores, eliminamos el fragmento de prueba de las inconsistencias anteriores.
Código para borrar el archivo de base de datos antes de cargarlo en el analizador:
Códigofrom datetime import datetime import re from unidecode import unidecode start = datetime.now() f= open('AS_HOUSE.462.xml', 'r',encoding='ANSI') def remove_non_ascii(text): return unidecode(unidecode(text)) for line in f: b=remove_non_ascii(line) for c in re.finditer(r'\w{5}NUM="\d{1,}\"\w\"',b): print(c[0]) c1=c[0][:-3]+c[0][-2] print(c1) b=b.replace(c[0],c1)
El código traduce caracteres no_ascii a la normalidad en el archivo xml y luego elimina los "" innecesarios en los nombres de edificios y casas.
Analizador de saxofón
Para comenzar, tome un pequeño archivo xml (58.8 MB), planeamos obtener txt o csv en la salida, conveniente para su posterior procesamiento en pandas o excel.
Código import xml.sax import csv from datetime import datetime start = datetime.now() class EventHandler(xml.sax.ContentHandler): def __init__(self,target): self.target = target def startElement(self,name,attrs): self.target.send(attrs._attrs.values()) def characters(self,text): self.target.send('') def endElement(self,name): self.target.send('') def coroutine(func): def start(*args,**kwargs): cr = func(*args,**kwargs) cr.__next__() return cr return start with open('out.csv', 'a') as f:
Después de ejecutar el programa, obtenemos los valores del diccionario python:

Plazo de ejecución: 5-6 seg.
Analizador DOM
Procesamos el mismo archivo cargándolo primero en su totalidad en la memoria. Este es exactamente el método que utiliza el analizador DOM.
Código import codecs,os import xml.etree.ElementTree as ET import csv from datetime import datetime parser = ET.XMLParser(encoding="ANSI") tree = ET.parse("out.xml",parser=parser) root = tree.getroot() Resident_data = open('AS_HOUSE.0001.csv', 'a',encoding='ANSI') csvwriter = csv.writer(Resident_data) attr_names = [ 'HOUSEID', 'HOUSEGUID', 'AOGUID', 'HOUSENUM', 'STRUCNUM', 'STRSTATUS', 'ESTSTATUS', 'STATSTATUS', 'IFNSFL', 'IFNSUL', 'TERRIFNSFL', 'TERRIFNSUL', 'OKATO', 'OKTMO', 'POSTALCODE', 'STARTDATE', 'ENDDATE', 'UPDATEDATE', 'COUNTER', 'NORMDOC', 'DIVTYPE', 'REGIONCODE' ] start = datetime.now() object = [] for member in root.findall('House'): object = [member.attrib.get(attr_name, None) for attr_name in attr_names] csvwriter.writerow(object) Resident_data.close() print(datetime.now()- start)
Tiempo de entrega 2-3 seg.
¿Ganar un analizador DOM?
Archivos más grandes
Los archivos pequeños no reflejan completamente la realidad. Tomemos un archivo de más de 353 MB (después de la limpieza, como se indicó anteriormente).
Resultados de hombro:
Analizador SAX: 0: 00: 32.090836 - 32 segundos
Analizador DOM: 0: 00: 16.630951 - 16 segundos
La diferencia es 2 veces la velocidad. Sin embargo, esto no resta valor a la ventaja principal del analizador SAX: la capacidad de procesar archivos grandes sin cargarlos primero en la memoria.
Queda lamentar que esta ventaja no sea aplicable a la base de datos FIAS, ya que se requiere un trabajo preliminar con codificaciones.
Archivo para limpieza preliminar de codificaciones:
- 353 MB en el
archivo .
Archivo DB purificado para pruebas de analizador:
- 353 MB en el
archivo .