首頁技術(shù)文章正文

lxml庫是干嘛的?Python lxml庫用法

更新時間:2021-06-21 來源:黑馬程序員 瀏覽量:

IT培訓班

lxml是使用Python語言編寫的庫,主要用于解析和提取HTML或者XML格式的數(shù)據(jù),它不僅功能非常豐富,而且便于使用,可以利用XPath語法快速地定位特定的元素或節(jié)點。

lxml庫中大部分功能都位于lxml.etree模塊中,導入lxml.etree模塊的常見方式如下:

from lxml import etree

lxml庫的一些相關(guān)類如下:
(1) Element類:可以理解為XML的節(jié)點。
(2) ElementTree類:可以理解為一個完整的XML文檔樹。
(3) ElementPath類:可以理解為XPath,用于搜索和定位節(jié)點。

1.Element 類簡介

Element類是XML處理的核心類,可以直觀地理解為XML的節(jié)點,大部分XML節(jié)點的處理都是圍繞著Element類進行的。要想創(chuàng)建一個節(jié)點對象,則可以通過構(gòu)造函數(shù)直接創(chuàng)建。例如:

root=etree.Element('root')

上述示例中,參數(shù)root表示節(jié)點的名稱。 關(guān)于Element類的相關(guān)操作,主要可分為三部分,分別是節(jié)點操作、節(jié)點屬性的操作、節(jié)點內(nèi)文本的操作,下面進行逐一介紹。 (1)節(jié)點操作:若要獲取節(jié)點的名稱,可以通過tag屬性獲取。例如:

print(root.tag)
# 輸出結(jié)果如下
root


(2)節(jié)點屬性的操作:在創(chuàng)建節(jié)點的同時,可以為節(jié)點增加屬性。節(jié)點中的屬性是以key-value的形式進行存儲的,類似于字典的存儲方式。通過構(gòu)造方法創(chuàng)建節(jié)點時,可以在該方法中以參數(shù)的形式設置屬性,其中參數(shù)的名稱表示屬性的名稱,參數(shù)的值表示為屬性的值。創(chuàng)建屬性的示例如下:

# 創(chuàng)建root節(jié)點,并為其添加屬性
root=etree.Element('root', interesting='totally')
print(etree.tostring(root))
# 輸出結(jié)果如下
b'<root interesting=" totally" />'

此外,可以通過set()方法給已有的節(jié)點添加屬性。在調(diào)用該方法時可以傳入兩個參數(shù),其中第一個參數(shù)表示屬性的名稱,第二個參數(shù)表示屬性的值。例如:

# 再次給root節(jié)點添加age屬性
root.set('age', '30')
print(etree.tostring(root))
# 輸出結(jié)果如下
b'<root interesting="totally"age="30"/>'

在上述兩個示例中,都用到了tostring()函數(shù),該函數(shù)可以將元素序列化為XML樹的編碼字符串表示形式。

(3)節(jié)點內(nèi)文本的操作:一般情況下,可以通過text、tail屬性或者xpath()方法來訪問文本內(nèi)容。通過text屬性訪問節(jié)點的示例如下:

root=etree.Element('root')    # 創(chuàng)建root節(jié)點
root.text='Hello, World!'    # 給root節(jié)點添加文本
print(root.text)
print(etree.tostring(root))
# 輸出結(jié)果如下
Hello, world!
b'<root>Hello, World!</root>'

2.從字符串或文件中解析XML

為了能夠?qū)ML文件解析為樹結(jié)構(gòu),etree模塊中提供了如下3個函數(shù): (1 ) fromstring()函數(shù):從字符串中解析XML文檔或片段,返回根節(jié)點(或解析器目標返回的結(jié)果)。 (2) XML()函數(shù):從字符串常量中解析XML文檔或片段,返回根節(jié)點(或解析器目標返回的結(jié)果)。 (3) HTML()函數(shù):從字符串常量中解析HTML文檔或片段,返回根節(jié)點(或解析器目標返回的結(jié)果)。 其中,XML()函數(shù)的行為類似于fromstring0函數(shù),通常用于將XML字面量直接寫入到源代碼中;HTML()函數(shù)可以自動補全缺少的<html>和<body>標簽。以上3個函數(shù)的示例如下:

xml_data='<root>data</root>'
# fromstring()方法
root_one=etree.fromstring(xml_data)
print(root_one.tag)
print(etree.tostring(root_one))
# XML方法,與fromstring方法基本一樣
root_two=etree.XML(xml_data)
print(root_two.tag)
print(etree.tostring(root_two))
# HTML()方法,如果沒有<html>和<body>標簽,會自動補上
root_three=etree.HTML(xml_data)
print(root_three.tag)
print(etree.tostring(root_three))
程序運行結(jié)果為:
root
b'<root>data</root>'
root
b'<root>data</root>'
html
b'<html><body><root>data</root></body></html>'

除了上述3個函數(shù)之外,還可以調(diào)用parse()函數(shù)從XML文件中直接解析。在調(diào)用函數(shù)時,如果沒有提供解析器,則使用默認的解析器,函數(shù)會返回一個ElemenfTree 類的對象。例如:

html=etree.parse('./hello.html')
result=etree.tostring(html, pretty_print=True)

ElementPath類簡介

ElementTree類中附帶了一個類似于XPath路徑語言的ElementPath類。在ElementTree類或Elements類的API文檔中,提供了3個常用的方法,可以滿足大部分搜索和查詢需求,并且這3個方法的參數(shù)都是XPath語句。具體如下: (1) find()方法:返回匹配到的第一 個子元素。 (2) findall()方法:以列表的形式返回所有匹配的子元素。 (3) iterfind()方法:返回一個所有匹配元素的迭代器。 從文檔樹的根節(jié)點開始,搜索符合要求的節(jié)點。例如:

# 從字符串中解析XML,返回根節(jié)點
root=etree.XML("<root><a x='123'>aText<b/><c/><b/></a></root>")
# 從根節(jié)點查找,返回匹配到的節(jié)點名稱
print(root.find("a").tag)
# 從根節(jié)點開始查找,返回匹配到的第一個節(jié)點的名稱
print(root.findall(".//a[@x]")[0].tag)

程序運行結(jié)果為:

a
A

還可以調(diào)用xpath()方法,使用元素作為上下文節(jié)點來評估XPath表達式。

lxml庫的基本使用

這里使用一個HTML示例文件作為素材來介紹lxml庫的基本應用。該文件名為hello.html,內(nèi)容如下:

<!-- hello.html -->
<div>
    <ul>
        <li class="item-0"><a href="link1.html">first item</a></li>
        <li class="item-1"><a href="link2.html">second item</a></li> 
        <li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>
        <li class="item-1"><a href="link4.html">fourth item</a></li>
        <li class="item-0"><a href="link5.html">fifth item</a></li>
    </ul>
</div>

按下來,基于上述HTML文檔,使用lxml庫中的路徑表達式技巧,通過調(diào)用xpath()方法匹配選取的節(jié)點,具體如下:

獲取任意位置的li節(jié)點 可以直接使用“//”從任意位置選取節(jié)點li,路徑表達式如下:

//li

通過lxml.etree模塊的xpath()方法,將hello.html文件中與該路徑表達式匹配到的列表返回,并打印輸出。具體代碼如下:

from lxml import etree
html=etree.parse('hello.html')
# 查找所有的li節(jié)點
result=html.xpath('//li')
# 打印<li>標簽的元素集合
print(result)
# 打印<li>標簽的個數(shù)
print(len(result))
# 打印返回結(jié)果的類型
print(type(result))
# 打印第一個元素的類型
print(type(result[0]))

程序運行結(jié)果為:

[<Element li at 0x2cc9a48>, <Element li at 0x2cc99c8>, <Element li at 0x2cc9a88>, <Element li at 0x2cc9ac8>, <Element li at 0x2cc9b08>]
5
<class 'list'>
<class 'lxml.etree._Element'>

繼續(xù)獲取<li>標簽的class屬性

在上個表達式的末尾,使用“/”向下選取節(jié)點,并使用@選取class屬性節(jié)點,表達式如下:

//1i/@class

獲取<li>標簽的class屬性的示例代碼如下:

from lxml import etree
html=etree.parse('hello.html')
# 查找位于li標簽的class屬性
result=html.xpath('//li/@class')
print(result)

程序運行結(jié)果為:

['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']

獲取倒數(shù)第二個元素的內(nèi)容

從任意位置開始選取倒數(shù)第二個<li>標簽,再向下選取標簽<a>。如果要獲取該標簽中的 文本,可以使用如下表達式:

//li[last()-1]/a

或者

//li[last()-1]/a]/text()

不同的是,第個表達式需要訪問text屬性,才能拿到標簽的文本,而第二個表達式可直 接獲取文本。使用第一 個路徑表達式的示例如下:

from lxml import etree
html=etree.parse('hello.html')
# 獲取倒數(shù)第二個元素的內(nèi)容
result=html.xpath('//li[last()-1]/a')
print(result[0].text)

程序運行結(jié)果:

fourth item


分享到:
在線咨詢 我要報名
和我們在線交談!