2014-10-18 55 views
2

我試圖解析以下料成的ElementTree在Python:「http://smarkets.s3.amazonaws.com/oddsfeed.xml」(警告大文件)解析壓縮的XML飼料到ElementTree的

這裏是我到目前爲止已經試過:

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) 

但它似乎只是掛在compressed_data = feed.read(),無限可能? (我知道這是一個很大的文件,但與我解析的其他非壓縮Feed相比,似乎太長了,而這個大文件首先會消除gzip壓縮帶來的任何帶寬收益)。

接下來我想requests,與

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

但現在

tree=ET.parse(r.content) 

tree=ET.parse(r.text) 

但這些引發異常。

這樣做的正確方法是什麼?

+0

「這些引發異常」沒有幫助。 _什麼例外?將追溯複製並粘貼到您的問題中。 – abarnert 2014-10-18 00:26:03

+0

另外,你爲什麼要嘗試傳遞一個HTTP頭作爲POST數據?他們不是一回事。 – abarnert 2014-10-18 00:26:40

回答

2

ET.parse函數採用「包含XML數據的文件名或文件對象」。你給它一個充滿XML的字符串。它將嘗試打開一個名爲XML的大文件的文件。可能沒有這樣的文件。

您想要fromstring函數或XML構造函數。或者,如果你願意,你已經有一個文件對象,gzipper;或者,你已經有一個文件對象,gzipper;您可以將其傳遞給parse而不是將其讀入字符串。


這是所有在文檔涵蓋的短Tutorial:從

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

或者直接:

我們可以從文件中讀取導入此數據一串:

root = ET.fromstring(country_data_as_string) 
4

您可以通過urlopen()返回的值直接傳遞到GzipFile()反過來,你可以把它傳遞給ElementTree方法,如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) 

其中getelements()允許解析不適合內存中的文件。

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 

爲了保存記憶,構造的XML樹的每個標籤元件上清除。