如何繼續獲取包含一段文本的節點的父節點?python,lxml或etree獲取包含某些文本的節點的父節點
此外,我可以使用一些正則表達式mecanism作爲搜索/過濾的匹配元素,例如從re.compile("th[ei]s? .ne")
下面搜索例如?
說this one
html = '''<html>
<head><title></title></head>
<body>
<table>
<tr><td>1a</td><td>2a</td><td>3a</td><td>4a</td><td>5a</td><td>6a</td></tr>
<tr><td>1b</td><td>2b</td><td>3b</td><td>4b</td><td>5b</td><td>6b</td></tr>
<tr><td>1c</td><td>2c</td><td>3c</td><td>4c</td><td>5c</td><td>6c this one</td></tr>
</table>
<div><div>
<table>
<tr><td>1A</td><td>2A</td><td>3A</td><td>4A</td><td>5A</td><td>6A</td></tr>
<tr><td>1B</td><td>2B</td><td>3B</td><td>4B</td><td>5B</td><td>6B</td></tr>
<tr><td>1C</td><td>2C</td><td>3C</td><td>4C</td><td>5C</td><td>6C</td></tr>
</table>this one
</div></div>
</body>
</html>'''
我想有一個返回一個迭代:
<td>6c this one</td>
然後:
<div>
<table>
<tr><td>1A</td><td>2A</td><td>3A</td><td>4A</td><td>5A</td><td>6A</td></tr>
<tr><td>1B</td><td>2B</td><td>3B</td><td>4B</td><td>5B</td><td>6B</td></tr>
<tr><td>1C</td><td>2C</td><td>3C</td><td>4C</td><td>5C</td><td>6C</td></tr>
</table>this one
</div>
我想:
import lxml.html
root = lxml.html.document_fromstring(html)
root.xpath("//text()[contains(., one)]")
和
import xml.etree.ElementTree as ET
for e in ET.fromstring(html).getiterator():
if e.text and e.text.find('one') != -1:
print "Found string %r, element = %r" % (e.text, e)
但最好我能有是包含this one
本身......而我找包含此文父節點。注意div或table只是例子,我真的需要在找到「this one」之後回溯到父級,而不是過濾包含this one
的xml元素,因爲我不知道這是一個div,表格或任何其他內容,然後才能找到它它包含。
(還要注意,它是HTML並不能很好格式化XML,因爲我想闕第二this one
應該已經包裝在XML標籤)
編輯:
>>> root.xpath("//*[contains(child::*/text(), 'one')]") # why empty parent?
[]
>>> root.xpath("//*[contains(text(), 'one')]") # i expected to have a list with two elements td and div
[<Element td at 0x280b600>]
>>> root.xpath("//*[child::*[contains(text(), 'one')]]") # if parent: expected tr and div, if not parent expected table or div, still missing one
[<Element tr at 0x2821f30>]
順便說一句,使用最後是確定的:
import xml.etree.ElementTree as ET
import lxml.html
#[... here add html = """...]
root = lxml.html.document_fromstring(html)
for i, x in enumerate(root.xpath("//text()[contains(., 'one')]/parent::*")):
print "%s => \n\t" % i, ET.tostring(x).replace("\n", "\n\t")
產品:
0 =>
<td>6c this one</td>
1 =>
<div>
<table>
<tr><td>1A</td><td>2A</td><td>3A</td><td>4A</td><td>5A</td><td>6A</td></tr>
<tr><td>1B</td><td>2B</td><td>3B</td><td>4B</td><td>5B</td><td>6B</td></tr>
<tr><td>1C</td><td>2C</td><td>3C</td><td>4C</td><td>5C</td><td>6C</td></tr>
</table>this one
</div>
是的,我需要包含指定文本的元素,因爲我認爲xml解析器認爲包含文本數據的「不可見」文本節點。不知道我在這裏。 順便說一句我不能得到父母,也沒有匹配節點(這裏是2)的列表看到我的編輯。以及關於如何在正則表達式上匹配的任何線索? – user1340802
對不起,我的第二個XPath不正確,我更新了它。你運行的第二個查詢也會期望兩個元素td和div,但是我得到的結果和你一樣。如果我使用另一個XPath/Xquery處理器運行這個程序,我會得到正確和預期的結果。這看起來像lxml中的一個bug。關於正則表達式,請在前幾天看看我的答案:http://stackoverflow.com/questions/16934852/lxml-find-div-with-id-post-0-9/16935525#16935525 – dirkk
對我來說第二個xpath看起來仍然不正確。 – user1340802