2011-01-14 10 views
13

मैं इस तरह की एक एक्सएमएल है:कुशल तरीका

<a> 
    <b>hello</b> 
    <b>world</b> 
</a> 
<x> 
    <y></y> 
</x> 
<a> 
    <b>first</b> 
    <b>second</b> 
    <b>third</b> 
</a> 

मैं सभी <a> और <b> टैग के माध्यम से पुनरावृति करने की जरूरत है, लेकिन मैं नहीं जानता कि उनमें से कितने दस्तावेज़ में हैं। इसलिए मैं उस को संभालने के लिए xpath का उपयोग करें:

from lxml import etree 

doc = etree.fromstring(xml) 

atags = doc.xpath('//a') 
for a in atags: 
    btags = a.xpath('b') 
    for b in btags: 
      print b 

यह काम करता है, लेकिन मैं बहुत बड़ी फ़ाइलों है, और cProfile मुझे पता चलता है कि xpath बहुत उपयोग करने के लिए महंगा है।

मुझे आश्चर्य है, शायद अनिश्चित काल तक एक्सएमएल-तत्वों के माध्यम से पुन: प्रयास करने के लिए और अधिक कुशल तरीका है?

+1

लिए बहुत उपयोगी है कृपया अनुवाद "बहुत बड़ी" मेगाबाइट में। –

उत्तर

17

XPath तेज़ होना चाहिए। आप कम कर सकते हैं XPath की संख्या एक के लिए कॉल:

doc = etree.fromstring(xml) 
btags = doc.xpath('//a/b') 
for b in btags: 
    print b.text 

अगर वह काफी तेजी से नहीं है, आप Liza Daly's fast_iter की कोशिश कर सकते। इसका लाभ यह नहीं है कि पूरे एक्सएमएल को पहले के साथ संसाधित किया जाए, और बच्चों के दौरे के बाद पैरेंट नोड्स फेंक दिए जाएंगे। इन दोनों चीजों में स्मृति आवश्यकताओं को कम करने में मदद मिलती है। नीचे a modified version of fast_iter है जो अब आवश्यक अन्य तत्वों को हटाने के बारे में अधिक आक्रामक है।

def fast_iter(context, func, *args, **kwargs): 
    """ 
    fast_iter is useful if you need to free memory while iterating through a 
    very large XML file. 

    http://lxml.de/parsing.html#modifying-the-tree 
    Based on Liza Daly's fast_iter 
    http://www.ibm.com/developerworks/xml/library/x-hiperfparse/ 
    See also http://effbot.org/zone/element-iterparse.htm 
    """ 
    for event, elem in context: 
     func(elem, *args, **kwargs) 
     # It's safe to call clear() here because no descendants will be 
     # accessed 
     elem.clear() 
     # Also eliminate now-empty references from the root node to elem 
     for ancestor in elem.xpath('ancestor-or-self::*'): 
      while ancestor.getprevious() is not None: 
       del ancestor.getparent()[0] 
    del context 

def process_element(elt): 
    print(elt.text) 

context=etree.iterparse(io.BytesIO(xml), events=('end',), tag='b') 
fast_iter(context, process_element) 

बड़े XML फ़ाइलों को पार्स भी आपके लिए उपयोगी साबित हो सकता है पढ़ने पर Liza Daly's article। लेख के अनुसार, fast_iter के साथ lxml cElementTree के iterparse से तेज़ हो सकता है। (तालिका 1 देखें)।

+0

fast_iter कोड में 'doc = etree.fromstring (xml)' का उद्देश्य क्या है ?? –

+0

@ जॉन मशीनिन: कॉपी-पेस्ट त्रुटि। इस पर ध्यान दिलाने के लिए धन्यवाद। – unutbu

+0

iterparse speed war: जैसा कि लेख बताता है, lxml तेज़ है यदि आप एक विशेष टैग चुनते हैं, और सामान्य पार्सिंग के लिए (आपको एकाधिक टैग की जांच करने की आवश्यकता है), cElementTree तेज़ है। –

10

कैसे iter?

>>> for tags in root.iter('b'):   # root is the ElementTree object 
...  print tags.tag, tags.text 
... 
b hello 
b world 
b first 
b second 
b third 
+0

वह लिंक मर चुका है; यहां एक लाइव है: http://lxml.de/tutorial.html#tree-iteration –

5

उपयोग iterparse:

import lxml.etree as ET 
    for event, elem in ET.iterparse(filelike_object): 
     if elem.tag == "a": 
      process_a(elem) 
      for child in elem: 
       process_child(child) 
      elem.clear() # destroy all child elements 
     elif elem.tag != "b": 
      elem.clear() 

ध्यान दें कि यह सब स्मृति को बचाने नहीं है, लेकिन मैं एक जीबी से अधिक की एक्सएमएल धाराओं इस तकनीक का इस्तेमाल की खोजबीन कर लिया है।

प्रयास करें import xml.etree.cElementTree as ET ... यह अजगर के साथ आता है और इसकी iterparselxml.etreeiterparse की तुलना में तेजी है, the lxml docs के अनुसार:

"" "अनुप्रयोग जो बड़ी फ़ाइलों के एक उच्च पार्सर प्रवाह क्षमता की आवश्यकता होती है, और कहा कि छोटे से करना कोई सीरियलाइजेशन नहीं है, सीईटी सबसे अच्छा विकल्प है। इसके अलावा उन अनुप्रयोगों के लिए जो बड़ी मात्रा में डेटा या बड़े एक्सएमएल डेटा सेट से कुल जानकारी निकालते हैं जो स्मृति में फिट नहीं होते हैं। अगर यह राउंड-ट्रिप प्रदर्शन की बात आती है, हालांकि, एलएक्सएमएल होता है कुल मिलाकर कई गुना तेजी से। इसलिए, जब भी इनपुट दस्तावेज़ आउटपुट से काफी बड़े नहीं होते हैं, तो एलएक्सएमएल स्पष्ट विजेता है। ""

-2

BS4 इस

from bs4 import BeautifulSoup 
raw_xml = open(source_file, 'r') 
soup = BeautifulSoup(raw_xml) 
soup.find_all('tags')