2010-11-07 10 views
16
<span class='python'> 
    <a>google</a> 
    <a>chrome</a> 
</span> 

मैं chrome प्राप्त करना चाहता हूं और इसे पहले से ही इस तरह काम कर रहा हूं।XPath के साथ दूसरा तत्व टेक्स्ट प्राप्त करें?

q = item.findall('.//span[@class="python"]//a') 
t = q[1].text # first element = 0 

मैं एक एकल XPath अभिव्यक्ति में यह गठबंधन करने के लिए और सिर्फ एक सूची के बजाय एक आइटम प्राप्त करना चाहते हैं।
मैंने कोशिश की लेकिन यह काम नहीं करता है।

t = item.findtext('.//span[@class="python"]//a[2]') # first element = 1 

और वास्तविक, सरलीकृत नहीं, HTML इस तरह है।

<span class='python'> 
    <span> 
    <span> 
     <img></img> 
     <a>google</a> 
    </span> 
    <a>chrome</a> 
    </span> 
</span> 
+2

आपका अभिव्यक्ति './/span[@class="python "] // एक [2] 'मेरे लिए काम करता है। –

+0

हम्म यह लगता है कि मुझे कहीं गलती है, या मैंने पोस्ट किए गए वास्तविक HTML का सरलीकरण _too_ सरल है। मैं कोशिश करूंगा और फिर प्रश्न को संशोधित करूंगा। –

+0

@pdnsk: अच्छा सवाल, +1। एक स्पष्टीकरण के लिए और एक सरल समाधान के लिए मेरा जवाब देखें। :) –

उत्तर

31

मैं इस कोशिश की, लेकिन यह काम नहीं करता।

t = item.findtext('.//span[@class="python"]//a[2]') 

यह // संक्षिप्त नाम के बारे में पूछे जाने वाले प्रश्न है।

.//a[2] का अर्थ है: वर्तमान a वर्तमान नोड के वंशज जो दूसरे a उनके माता-पिता के बच्चे हैं, का चयन करें। कंक्रीट एक्सएमएल दस्तावेज़ के आधार पर यह एक से अधिक तत्व या कोई तत्व नहीं चुन सकता है।

इसे और अधिक सरलता से रखने के लिए, [] ऑपरेटर // से अधिक प्राथमिकता है।

यदि आप चाहते हैं सिर्फ एक (दूसरा) सभी नोड्स के लिए लौट आए हैं कि आप अपने वांछित पूर्वता मजबूर करने के लिए कोष्ठक का उपयोग करना पड़:

(.//a)[2]

यह वास्तव में वर्तमान नोड के दूसरे a वंशज चयन करता है।

विचाराधीन इस्तेमाल किया अभिव्यक्ति के लिए, के लिए इसे बदल:

(.//span[@class="python"]//a)[2] 

या के लिए इसे बदल:

(.//span[@class="python"]//a)[2]/text() 
+0

स्पष्टीकरण के लिए धन्यवाद, लेकिन मेरे पास एक प्रश्न है, या वास्तव में दो। यदि केवल एक मिलान तत्व है, तो '[2]' अपवाद फेंक देगा या 'कोई नहीं' वापस करेगा? और क्या आप जानते हैं कि यह 'xpath' के साथ क्यों काम करता है लेकिन 'findtext' नहीं? –

+1

@pdnsk: मेरा जवाब शुद्ध XPath है। मुझे पायथन नहीं पता। –

+0

मैंने कोशिश की और यह सिर्फ कोई तत्व नहीं लौटाता, जो कि अच्छा है क्योंकि एक कारण है कि मैं सूचियों से बचना चाहता हूं और इसे एक अभिव्यक्ति में रखना चाहता हूं, अतिरिक्त जांच नहीं है। –

2

मुझे यकीन है कि समस्या क्या है नहीं कर रहा हूँ ...

>>> d = """<span class='python'> 
... <a>google</a> 
... <a>chrome</a> 
... </span>""" 
>>> from lxml import etree 
>>> d = etree.HTML(d) 
>>> d.xpath('.//span[@class="python"]/a[2]/text()') 
['chrome'] 
>>> 
+0

धन्यवाद, यह काम करता है। ऐसा लगता है कि 'findtext' समस्या है। –

2

टिप्पणियाँ से:

या वास्तविक एचटीएमएल मैं पोस्ट के सरलीकरण भी आसान है

आप सही हैं। .//span[@class="python"]//a[2] का अर्थ क्या है? यह करने के लिए विस्तार किया जाएगा:

self::node() 
/descendant-or-self::node() 
    /child::span[attribute::class="python"] 
    /descendant-or-self::node() 
    /child::a[position()=2] 

यह अंत में दूसरी a बच्चे का चयन करेंगे (fn:position()child कुल्हाड़ी को संदर्भित करता है)। तो, कुछ भी नहीं है का चयन हो सकता है अगर आपके दस्तावेज़ की तरह है:

<span class='python'> 
    <span> 
    <span> 
     <img></img> 
     <a>google</a><!-- This is the first "a" child of its parent --> 
    </span> 
    <a>chrome</a><!-- This is also the first "a" child of its parent --> 
    </span> 
</span> 

आप सभी सन्तान, उपयोग की दूसरी चाहते हैं:

descendant::span[@class="python"]/descendant::a[2] 
+0

धन्यवाद, मैंने सवाल अपडेट किया। –

+0

यह 'xpath' के साथ काम करता है लेकिन' findtext' के साथ नहीं, और एक आइटम के साथ एक सूची देता है। –

+0

@pdknsk: ऐसा इसलिए है क्योंकि यह XPath अभिव्यक्ति एक नोड सेट परिणाम देता है: यह खाली हो सकता है, यह एक सिंगलटन हो सकता है, यह "पायथन" वर्ग के साथ एक दूसरे वंशज के साथ कई स्पैन हो सकता है ... यदि आप ** इस परिणामों के पहले के स्ट्रिंग मान **, तर्क के रूप में इस अभिव्यक्ति के साथ 'स्ट्रिंग()' फ़ंक्शन का उपयोग करें। मुझे नहीं पता कि किस प्रकार का डेटा प्रकार आपकी 'xpath' विधि वापस कर सकता है ... –

संबंधित मुद्दे