library example etree dict create python xml gzip elementtree

example - xml python 3



Analizar la alimentaciĆ³n xml comprimida en ElementTree (2)

Estoy tratando de analizar el siguiente feed en ElementTree en python: " http://smarkets.s3.amazonaws.com/oddsfeed.xml " (archivo grande de advertencia)

Esto es lo que he intentado hasta ahora:

feed = urllib.urlopen("http://smarkets.s3.amazonaws.com/oddsfeed.xml") # feed is compressed compressed_data = feed.read() import StringIO compressedstream = StringIO.StringIO(compressed_data) import gzip gzipper = gzip.GzipFile(fileobj=compressedstream) data = gzipper.read() # Parse XML tree = ET.parse(data)

pero parece que se cuelga en compressed_data = feed.read() , infinitamente tal vez? (Sé que es un archivo grande, pero parece demasiado largo en comparación con otros feeds no comprimidos que analicé, y este tamaño está matando cualquier ganancia de ancho de banda de la compresión gzip en primer lugar).

Luego probé las requests , con

url = "http://smarkets.s3.amazonaws.com/oddsfeed.xml" headers = {''accept-encoding'': ''gzip, deflate''} r = requests.get(url, headers=headers, stream=True)

pero ahora

tree=ET.parse(r.content)

o

tree=ET.parse(r.text)

pero estos levantan excepciones.

¿Cuál es la forma correcta de hacer esto?


La función ET.parse toma "un nombre de archivo o un objeto de archivo que contiene datos XML". Le estás dando una cadena llena de XML. Intentará abrir un archivo cuyo nombre es ese gran fragmento de XML. Probablemente no hay tal archivo.

Desea la función fromstring o el constructor XML .

O, si lo prefiere, ya tiene un objeto de archivo, gzipper ; podrías pasar eso para parse lugar de leerlo en una cadena.

Todo esto está cubierto por el breve Tutorial en los documentos:

Podemos importar estos datos leyendo de un archivo:

import xml.etree.ElementTree as ET tree = ET.parse(''country_data.xml'') root = tree.getroot()

O directamente de una cadena:

root = ET.fromstring(country_data_as_string)


Puede pasar el valor devuelto por urlopen() directamente a GzipFile() y, a su vez, puede pasarlo a métodos iterparse() como iterparse() :

#!/usr/bin/env python3 import xml.etree.ElementTree as etree from gzip import GzipFile from urllib.request import urlopen, Request with urlopen(Request("http://smarkets.s3.amazonaws.com/oddsfeed.xml", headers={"Accept-Encoding": "gzip"})) as response, / GzipFile(fileobj=response) as xml_file: for elem in getelements(xml_file, ''interesting_tag''): process(elem)

donde getelements() permite analizar archivos que no caben en la memoria.

def getelements(filename_or_file, tag): """Yield *tag* elements from *filename_or_file* xml incrementaly.""" context = iter(etree.iterparse(filename_or_file, events=(''start'', ''end''))) _, root = next(context) # get root element for event, elem in context: if event == ''end'' and elem.tag == tag: yield elem root.clear() # free memory

Para preservar la memoria, el árbol xml construido se borra en cada elemento de etiqueta .