python-爬蟲基礎-lxml.etree(2)

(5)元素包含文本

文本包含元素中間文本和末尾文本,例如,<body></body>中間的文本爲中間文本,<br/>之後的文本爲元素末尾文本。

root = etree.Element("root")
root.text = "TEXT"
print(root.text)
print(etree.tostring(root))
#加html節點
html = etree.Element("html")
#加body節點
body = etree.SubElement(html,"body")
#body標籤內加入文本
body.text = "TEXT"
#打印html以及之下的節點
print(etree.tostring(html))
#加入br節點
br = etree.SubElement(body,"br")
print(etree.tostring(html))
#元素通過它們的 tail 屬性在末尾加text
br.tail = "TALL"
print(etree.tostring(html))
'''
在某些情況下,尾部文本也會成爲障礙。 
例如,當您從樹中序列化一個 Element 時,
您並不總是希望其尾部文本出現在結果中
(儘管您仍然希望其子元素的尾部文本)。 
爲此,tostring ()函數接受帶有 tail 的關鍵字參數:
'''
#打印節點包含尾節點
print(etree.tostring(br))
#打印節點不包含未節點
print(etree.tostring(br,with_tail=False))

返回結果

b'<root>TEXT</root>'
b'<html><body>TEXT</body></html>'
b'<html><body>TEXT<br/></body></html>'
b'<html><body>TEXT<br/>TALL</body></html>'
b'<br/>TALL'
b'<br/>'

(6)XPath 查找文本

種提取樹中文本內容的方法是 XPath

#查找文本,允許您將單獨的文本塊提取到一個列表中
print(html.xpath("string()"))
print(html.xpath("//text()"))
#可以將文本包裝成函數,方便以後使用
build_test_list = etree.XPath("//text()")
print(build_test_list(html))
#查詢返回字符串的父節點
texts = build_test_list(html)
print(texts[0])
parent = texts[0].getparent()
print(parent.tag)
print(texts[1])
print(texts[1].getparent().tag)
# 它是正常的文本內容還是尾部文本
print(texts[0].is_text)
print(texts[1].is_text)
print(texts[1].is_tail)

返回結果

TEXTTALL
['TEXT', 'TALL']
['TEXT', 'TALL']
TEXT
body
TALL
br
True
False
True

(7)樹迭代

對於像上面這樣的問題,您希望遞歸遍歷樹並對其元素執行某些操作,樹迭代是一個非常方便的解決方案。 元素爲此提供了一個樹迭代器。 它按照文檔順序生成元素,也就是說,如果你把樹序列化爲 XML,元素的標籤就會按照順序出現:

root = etree.Element("root")
etree.SubElement(root, "child").text = "Child 1"
etree.SubElement(root, "child").text = "Child 2"
etree.SubElement(root, "another").text = "Child 3"
print(etree.tostring(root, pretty_print=True))
#循環遍歷樹
for element in root.iter():
    print("%s - %s" % (element.tag, element.text))
#按條件過濾(單個或者多個)
for element in root.iter("child"):
    print("%s - %s" % (element.tag, element.text))
for element in root.iter("another", "child"):
    print("%s - %s" % (element.tag, element.text))
'''
默認情況下,迭代生成樹中的所有節點,
包括 ProcessingInstructions、 Comments 和 Entity 實例。
 如果你想確保只返回 Element 對象,你可以傳遞 Element factory 作爲標籤參數:
'''
root.append(etree.Entity("#234"))
root.append(etree.Comment("some comment"))
for element in root.iter():
    if isinstance(element.tag, str):  # or 'str' in Python 3
        print("%s - %s" % (element.tag, element.text))
    else:
        print("SPECIAL: %s - %s" % (element, element.text))
for element in root.iter(tag=etree.Element):
    print("%s - %s" % (element.tag, element.text))
for element in root.iter(tag=etree.Entity):
    print(element.text)

返回結果

b'<root>\n  <child>Child 1</child>\n  <child>Child 2</child>\n  <another>Child 3</another>\n</root>\n'
root - None
child - Child 1
child - Child 2
another - Child 3
child - Child 1
child - Child 2
child - Child 1
child - Child 2
another - Child 3
root - None
child - Child 1
child - Child 2
another - Child 3
SPECIAL: &#234; - &#234;
SPECIAL: <!--some comment--> - some comment
root - None
child - Child 1
child - Child 2
another - Child 3
&#234;

注意,傳遞一個通配符“ * ”標記名也會產生所有的 Element 節點(只有元素)。

在 lxml.etree 中,元素爲樹中的所有方向提供了進一步的迭代器: 子元素、父元素(或者更確切地說是祖先元素)和兄弟元素。

(8)序列化

序列化通常使用返回字符串的 tostring ()函數,或者使用 ElementTree.write ()方法寫入文件、類似文件的對象或 URL (通過 FTP PUT 或 HTTP POST)。 這兩個調用都接受相同的關鍵字參數,比如用於格式化輸出的 pretty print 或者用於選擇一個特定的輸出編碼的編碼,而不是普通的 ASCII:

root = etree.XML('<root><a><b/></a></root>')
print(etree.tostring(root))
print(etree.tostring(root, xml_declaration=True))
print(etree.tostring(root, encoding='iso-8859-1'))
print(etree.tostring(root, pretty_print=True))
'''
在 lxml 2.0和更高版本(以及 ElementTree 1.3)中,
序列化函數可以做的不僅僅是 XML 序列化。 
你可以序列化爲 HTML,或者通過傳遞 method 關鍵字來提取文本內容:
'''
root = etree.XML( '<html><head/><body><p>Hello<br/>World</p></body></html>')
print(etree.tostring(root)) # default: method = 'xml'
print(etree.tostring(root, method='xml')) # same as above
print(etree.tostring(root, method='html'))
print(etree.tostring(root, method='html', pretty_print=True))
print(etree.tostring(root, method='text'))
'''
在這裏,序列化爲 Python unicode 字符串而不是字節字符串
可能會變得很方便。 只需將名稱“ unicode”作爲編碼傳遞:
'''
print(etree.tostring(root, encoding='unicode', method='text'))

返回結果

b'<root><a><b/></a></root>'
b"<?xml version='1.0' encoding='ASCII'?>\n<root><a><b/></a></root>"
b"<?xml version='1.0' encoding='iso-8859-1'?>\n<root><a><b/></a></root>"
b'<root>\n  <a>\n    <b/>\n  </a>\n</root>\n'
b'<html><head/><body><p>Hello<br/>World</p></body></html>'
b'<html><head/><body><p>Hello<br/>World</p></body></html>'
b'<html><head></head><body><p>Hello<br>World</p></body></html>'
b'<html>\n<head></head>\n<body><p>Hello<br>World</p></body>\n</html>\n'
b'HelloWorld'
HelloWorld

W3C有一篇關於 Unicode字符集和字符編碼的好文章。https://www.w3.org/International/tutorials/tutorial-char-enc/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章