編程學習網 > 編程語言 > Python > Python使用lxml處理XML及網頁抓取教程
2023
08-31

Python使用lxml處理XML及網頁抓取教程

在本教程中,我們會學習lxml庫和創建XML文檔的基礎知識,然后會處理XML和HTML文檔。最后,我們將利用以上所學,融會貫通,看看如何使用lxml提取數據。本教程的每一步都配有實用的Python lxml示例。

閱讀人群
本教程適用于對Python、XML和HTML有基本的了解的開發人員。簡單地說,如果您知道XML中的屬性是什么,那么就足以理解本文。
本教程使用Python3代碼段,但所有內容都可以在Python2上運行,只需進行少量更改。
 
Python中的lxml是什么?
lxml是在Python中處理XML和HTML最快且功能豐富的庫之一。該庫本質上是C庫libxml2和libxslt的封裝。因此結合了C庫的速度和Python的簡單性。
使用Python lxml庫,可以創建、解析和查詢XML和HTML文檔。它依賴于許多其他復雜的包,如Scrapy。

01#安裝
下載和安裝lxml庫的最佳方法是去Python Package Index(PyPI):
https://pypi.org/project/lxml/
如果您使用的是Linux(基于debian),只需運行:
  sudo apt-get install python3-lxml
另一種方法是使用pip包管理器。這適用于Windows、Mac和Linux:
  pip3 install lxml
在Windows上,假設您正在運行Python3,只需使用pip install lxml。

02#創建一個簡單的XML文檔

任何XML或任何符合XML的HTML都可以看作一棵樹。一棵樹有根和樹枝。樹的每個分支可以具有更多分支。所有這些分支和根都分別表示一個Element。

一個非常簡單的XML文檔如下所示:


<root>
       <branch>
        <branch_one>
       </branch_one>
       <branch_one>
       </branch_one>
       <branch>
</root>

如果HTML是兼容XML的,它將遵循相同的概念。
請注意,HTML可能兼容也可能不兼容XML。例如,如果HTML的<br>沒有相應的結束標記,它仍然是有效的HTML,但它不會是有效的XML。
在本教程的后半部分,我們將看看如何處理這些情況。接下來讓我們專注于兼容XML的HTML。

03#元素類

使用python lxml創建XML文檔,第一步是導入lxml的etree模塊:
>>> from lxml import etree
每個XML文檔都以根元素開始??梢允褂迷仡愋蛣摻?。元素類型是一個靈活的容器對象,可以存儲分層數據??梢悦枋鰹樽值浜土斜碇g的交叉。
在這個python lxml示例中,目標是創建一個兼容XML的HTML。這意味著根元素的名稱將是html:
>>> root = etree.Element("html")
同樣,每個html都會有一個頭部和一個主體:
>>> head = etree.Element("head")
>>> body = etree.Element("body")

要創建父子關系,我們可以簡單地使用append()方法。

>>> root.append(head)

>>> root.append(body)

在tostring()函數的幫助下,這個文檔可以被序列化并輸出到終端。此函數需要一個強制參數,即文檔的根。我們可以選擇將pretty_print設置為True以使輸出更具可讀性。
請注意,tostring()序列化程序會實際返回字節。這可以通過調用decode()轉換為字符串:
>>> print(etree.tostring(root, pretty_print=True).decode())

04#子元素類

創建一個Element對象并調用append()函數會使代碼變得混亂和不可讀。最簡單的方法是使用SubElement類型。它的構造函數有兩個參數——父節點和元素名稱。使用SubElement,以下兩行代碼可以替換為一行。
body = etree.Element("body")
root.append(body)
# is same as
body = etree.SubElement(root,"body")

05#設置文本和屬性

使用lxml庫設置文本非常容易。Element和SubElement的每個實例都公開了兩個方法——text和set,前者用于指定文本,后者用于設置屬性。以下是示例:
para = etree.SubElement(body, "p")
para.text="Hello World!"
同樣,可以使用鍵值約定設置屬性:
para.set("style", "font-size:20pt")

要注意的是,可以在SubElement的構造函數中傳遞該屬性:
para = etree.SubElement(body, "p", style="font-size:20pt", id="firstPara")
para.text = "Hello World!"

這種方法的節省了代碼行數,代碼可讀性也更強。這是完整的代碼。將它保存在一個python文件中并運行它。它將輸出一個HTML,它也是一個格式良好的XML。
from lxml import etree
root = etree.Element("html")
head = etree.SubElement(root, "head")
title = etree.SubElement(head, "title")
title.text = "This is Page Title"
body = etree.SubElement(root, "body")
heading = etree.SubElement(body, "h1", style="font-size:20pt", id="head")
heading.text = "Hello World!"

para = etree.SubElement(body, "p",  id="firstPara")

para.text = "This HTML is XML Compliant!"

para = etree.SubElement(body, "p",  id="secondPara")

para.text = "This is the second paragraph."
etree.dump(root)  # prints everything to console. Use for debug only

請注意,這里我們使用了etree.dump()而不是調用etree.tostring()。不同之處在于dump()只是將所有內容寫入控制臺而不返回任何內容,tostring()用于序列化并返回一個字符串,您可以將其存儲在變量中或寫入文件。dump()僅適用于調試,不應用于任何其他目的。

在代碼段的底部添加以下幾行并再次運行它:
with open(‘input.html’, ‘wb’) as f:
f.write(etree.tostring(root, pretty_print=True)

代碼會將內容保存到您運行腳本的同一文件夾中的input.html。同樣,這是一個格式良好的XML,可以看作XML或HTML。

如何在Python中使用LXML
解析XML文件?

上一節是關于創建XML文件的Python lxml教程。在本節中,我們將研究如何使用lxml庫遍歷和操作現有的XML文檔。

在我們繼續之前,將以下代碼段保存為input.html。

<html>

  <head>

 <title>This is Page Title</title>

  </head>

  <body>

 <h1 style="font-size:20pt" id="head">Hello World!</h1>

 <p id="firstPara">This HTML is XML Compliant!</p>

 <p id="secondPara">This is the second paragraph.</p>

  </body>

</html>

解析XML文檔時,結果是內存中的ElementTree對象。

原始XML內容可以在文件系統或字符串中。如果它在文件系統中,則可以使用parse方法加載它。請注意,parse方法將返回一個ElementTree類型的對象。要獲取根元素,只需調用getroot()方法。

from lxml import etree

tree = etree.parse('input.html')

elem = tree.getroot()

etree.dump(elem) #prints file contents to console

lxml.etree模塊公開了另一種可用于有效解析xml字符串中內容的方法—fromstring()

xml ='<html><body>Hello</body></html>'

root = etree.fromstring(xml)

etree.dump(root)

這里要注意的一個重要區別是fromstring()方法會返回一個元素對象。無需調用getroot()。

如果您想深入了解解析,復制以下內容到瀏覽器了解BeautifulSoup教程的詳細內容:

https://oxylabs.io/blog/beautiful-soup-parsing-tutorial


這是一個用于解析HTML和XML文檔的Python包。但是為了快速回答BeautifulSoup中的lxml是什么,lxml可以使用BeautifulSoup作為解析器后端。同樣,BeautifulSoup可以使用lxml作為解析器。

在XML中查找元素

從廣義上講,有兩種使用Python lxml庫查找元素的方法。第一種是使用Python lxml查詢語言:XPath和ElementPath。例如,以下代碼將返回第一個段落元素。



請注意,選擇器與XPath非常相似。另請注意,未使用根元素名稱,因為elem包含XML樹的根。

tree = etree.parse('input.html')

elem = tree.getroot()

para = elem.find('body/p')

etree.dump(para)

# Output

# <p id="firstPara">This HTML is XML Compliant!</p>

類似地,findall()將返回與選擇器匹配的所有元素的列表。

elem = tree.getroot()

para = elem.findall('body/p')

for e in para:

 etree.dump(e)

# Outputs

# <p id="firstPara">This HTML is XML Compliant!</p>

# <p id="secondPara">This is the second paragraph.</p>

選擇元素的第二種方法是直接使用XPath。熟悉XPath的開發人員更容易使用這種方法。此外,XPath可用于使用標準XPath語法返回元素的實例、文本或任何屬性的值。

para = elem.xpath('//p/text()')

for e in para:

print(e)

# Output

# This HTML is XML Compliant!

# This is the second paragraph.

使用lxml.html處理HTML

在本文中,我們一直在使用兼容XML的格式良好的HTML。很多時候情況并非如此。對于這些場景,您可以簡單地使用lxml.html而不是lxml.etree。



請注意,不支持直接從文件中讀取。文件內容應首先以字符串形式讀取。這是從同一HTML文件輸出所有段落的代碼。

from lxml import html

with open('input.html') as f:

html_string = f.read()

tree = html.fromstring(html_string)

para = tree.xpath('//p/text()')

for e in para:

print(e)

# Output

# This HTML is XML Compliant!

# This is the second paragraph

lxml網頁抓取教程

現在我們知道如何解析和查找XML和HTML中的元素,唯一缺少的部分是獲取網頁的HTML。

為此,“requests”庫是一個不錯的選擇。它可以使用pip包管理器安裝:

pip install requests

一旦安裝了requests庫,就可以使用簡單的get()方法檢索任何網頁的HTML。示例如下:

import requests

response = requests.get('http://books.toscrape.com/')

print(response.text)

# prints source HTML



可以與lxml結合以檢索所需的任何數據。

這是一個輸出維基百科國家列表的簡單示例:

import requests

from lxml import html

response = requests.get('https://en.wikipedia.org/wiki/List_of_countries_by_population_in_2010')

tree = html.fromstring(response.text)

countries = tree.xpath('//span[@class="flagicon"]')

for country in countries:

    print(country.xpath('./following-sibling::a/text()')[0])



在這段代碼中,response.text返回的HTML被解析為變量樹??梢允褂脴藴蔢Path語法進行查詢,連接XPath。請注意,xpath()方法返回一個列表,因此在此代碼片段中僅獲取第一項。



這可以很容易地擴展為從HTML讀取任何屬性。例如,以下修改后的代碼輸出結果為國旗的國家名稱和圖像URL。

for country in countries:

flag = country.xpath('./img/@src')[0]

country = country.xpath('./following-sibling::a/text()')[0]

print(country, flag)

—— 結論 ——

在這個Python lxml教程中,介紹了使用lxml庫處理XML和HTML。Python lxml庫是一個輕量級、快速且功能豐富的庫??捎糜趧摻╔ML文檔、讀取現有文檔和查找特定元素。這個庫對于XML和HTML文檔同樣強大。結合Requests庫,它也可以很容易地用于網頁抓取。

以上就是Python使用lxml處理XML及網頁抓取教程的詳細內容,想要了解更多Python教程歡迎持續關注編程學習網。

掃碼二維碼 獲取免費視頻學習資料

Python編程學習

查 看2022高級編程視頻教程免費獲取