當爬取到Html數據後,能夠用正則對數據進行提取,但有時候正則表達式編寫起來不方便,並且萬一寫錯了,可能致使匹配失敗。這時候就須要藉助其餘解析工具了。
W3School官方文檔:http://www.w3school.com.cn/xm...html
語法要求不一樣node
設計目標不一樣python
一、父(parent)
每一個元素以及屬性都有一個父。
下面是一個簡單的XML例子中,book 元素是 title、author、year 以及 price 元素的父:git
<?xml version="1.0" encoding="utf-8"?> <book> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book>
二、 子(Children)
元素節點可有零個、一個或多個子。
在下面的例子中,title、author、year 以及 price 元素都是 book 元素的子:github
<?xml version="1.0" encoding="utf-8"?> <book> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book>
三、 同胞(Sibling)
擁有相同的父的節點
在下面的例子中,title、author、year 以及 price 元素都是同胞:正則表達式
<?xml version="1.0" encoding="utf-8"?> <book> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book>
四、 先輩(Ancestor)
某節點的父、父的父,等等。
在下面的例子中,title 元素的先輩是 book 元素和 bookstore 元素:ubuntu
<?xml version="1.0" encoding="utf-8"?> <bookstore> <book> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> </bookstore>
五、 後代(Descendant)
某個節點的子,子的子,等等。
在下面的例子中,bookstore 的後代是 book、title、author、year 以及 price 元素:工具
<?xml version="1.0" encoding="utf-8"?> <bookstore> <book> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> </bookstore>
Xpath,全稱XML Path Language,即XML路徑語言,它是一門在XML文檔中查找信息的語言,可用來在 XML 文檔中對元素和屬性進行遍歷。。最初是用來搜尋XML文檔的,可是它也適用與HTML文檔的搜索。
因此在作爬蟲時,可使用XPath來作相應的信息抽取。開發工具
W3School官方文檔:http://www.w3school.com.cn/xp...ui
XPath 使用路徑表達式來選取 XML 文檔中的節點或者節點集。這些路徑表達式和咱們在常規的電腦文件系統中看到的表達式很是類似。
一、Xpath經常使用規則
表達式 | 描述 |
---|---|
nodename | 選取此節點的全部子節點 |
/ | 從當前節點選取直接子節點 |
// | 從當前節點選取子孫節點 |
. | 選取當前節點 |
.. | 選取當前節點的父節點 |
@ | 選取屬性 |
二、Xpath使用示例
如下面xmL文檔爲例:
<?xml version="1.0" encoding="utf-8"?> <bookstore> <book> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> </bookstore>
路徑表達式 | 結果 |
---|---|
bookstore | 選取bookstore元素的全部子節點 |
/bookstore | 選取根元素bookstore。注:假如路徑起始於正斜槓/,則此路徑表明某元素的絕對路徑 |
bookstore/book | 選取屬於bookstore的子元素的全部book元素 |
//book | 選取全部book元素,無論在文檔的任何位置 |
bookstore//book | 選擇屬於 bookstore 元素的後代的全部 book 元素,而無論它們位於 bookstore 之下的什麼位置。 |
//@lang | 選取名爲lang的全部屬性 |
一、window安裝
cmd進入命令行模式,執行
pip3 install lxml
二、ubuntu16.04安裝
ctrl+alt+t進入終端模式,執行:
sudo apt-get install -y build-essential libssl-devl libffi-dev libxml2-dev libxslt1-dev zlib1g-dev
安裝依賴的類庫後,執行pip安裝:
sudo pip3 install lxml
三、驗證安裝
導入lxml模塊,若是沒有報錯就安裝成功。
$ python3 >>> import lxml
初步使用
文件名lxml_test.py
# 使用 lxml 的 etree 庫 from lxml import etree text = ''' <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">third item</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> ''' #利用etree.HTML,將字符串解析爲HTML文檔,etree模塊可自動修正HTML文本 html = etree.HTML(text) # 按字符串序列化HTML文檔 ret = etree.tostring(html) # torstring()方法返回的結果是bytes類型,這裏用decode()方法將其轉化爲字符串 print(ret.decode('utf-8'))
輸出結果:
<html><body> <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">third item</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> </body></html>
etree
模塊能夠自動修正 html 代碼,例子裏不只補全了 li 標籤,還添加了 body,html 標籤。
文件讀取
除了直接讀取字符串,lxml還支持從文件裏讀取內容。這裏我將上面的lxml_test.py文件執行後的內容保存爲test.html
python lxml_test.py >> test.html
內容就是上面的輸出結果 cat test.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>
使用etree.parse()方法來讀取文件。
from lxml import etree html = etree.parse('./test.html',HTMLParser()) ret = etree.tostring(html) print(ret.decode('utf-8'))
輸出結果
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <html><body> <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">third item</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> </body></html>
輸出結果多了一個DOCTYPE聲明,對解析結果沒影響。