lxml模塊
知識(shí)點(diǎn)
- 了解 lxml模塊和xpath語(yǔ)法的關(guān)系
- 了解 lxml模塊的使用場(chǎng)景
- 了解 lxml模塊的安裝
- 了解 谷歌瀏覽器xpath helper插件的安裝和使用
- 掌握 xpath語(yǔ)法-基礎(chǔ)節(jié)點(diǎn)選擇語(yǔ)法
- 掌握 xpath語(yǔ)法-節(jié)點(diǎn)修飾語(yǔ)法
- 掌握 xpath語(yǔ)法-其他常用語(yǔ)法
- 掌握 lxml模塊中使用xpath語(yǔ)法定位元素提取屬性值或文本內(nèi)容
- 掌握 lxml模塊中etree.tostring函數(shù)的使用
1. 了解 lxml模塊和xpath語(yǔ)法
對(duì)html或xml形式的文本提取特定的內(nèi)容,就需要我們掌握l(shuí)xml模塊的使用和xpath語(yǔ)法。
- lxml模塊可以利用XPath規(guī)則語(yǔ)法,來(lái)快速的定位HTML\XML 文檔中特定元素以及獲取節(jié)點(diǎn)信息(文本內(nèi)容、屬性值)
- XPath (XML Path Language) 是一門在 HTML\XML 文檔中查找信息的語(yǔ)言,可用來(lái)在 HTML\XML 文檔中對(duì)元素和屬性進(jìn)行遍歷。
- W3School官方文檔:http://www.w3school.com.cn/xpath/index.asp
- 提取xml、html中的數(shù)據(jù)需要lxml模塊和xpath語(yǔ)法配合使用
知識(shí)點(diǎn):了解 lxml模塊和xpath語(yǔ)法
2. 谷歌瀏覽器xpath helper插件的安裝和使用
要想利用lxml模塊提取數(shù)據(jù),需要我們掌握xpath語(yǔ)法規(guī)則。接下來(lái)我們就來(lái)了解一下xpath helper插件,它可以幫助我們練習(xí)xpath語(yǔ)法
2.1 谷歌瀏覽器xpath helper插件的作用
在谷歌瀏覽器中對(duì)當(dāng)前頁(yè)面測(cè)試xpath語(yǔ)法規(guī)則
2.2 谷歌瀏覽器xpath helper插件的安裝和使用
我們以windos為例進(jìn)行xpath helper的安裝
2.2.1 xpath helper插件的安裝
下載Chrome插件 XPath Helper
把文件的后綴名crx改為rar,然后解壓到同名文件夾中
把解壓后的文件夾拖入到已經(jīng)開(kāi)啟開(kāi)發(fā)者模式的chrome瀏覽器擴(kuò)展程序界面


- 重啟瀏覽器后,訪問(wèn)url之后在頁(yè)面中點(diǎn)擊xpath圖標(biāo),就可以使用了

- 如果是linux或macOS操作系統(tǒng),無(wú)需操作上述的步驟2,直接將crx文件拖入已經(jīng)開(kāi)啟開(kāi)發(fā)者模式的chrome瀏覽器擴(kuò)展程序界面
知識(shí)點(diǎn):了解 谷歌瀏覽器xpath helper插件的安裝和使用
3. xpath的節(jié)點(diǎn)關(guān)系
學(xué)習(xí)xpath語(yǔ)法需要先了解xpath中的節(jié)點(diǎn)關(guān)系
3.1 xpath中的節(jié)點(diǎn)是什么
每個(gè)html、xml的標(biāo)簽我們都稱之為節(jié)點(diǎn),其中最頂層的節(jié)點(diǎn)稱為根節(jié)點(diǎn)。我們以xml為例,html也是一樣的

3.2 xpath中節(jié)點(diǎn)的關(guān)系

author是title的第一個(gè)兄弟節(jié)點(diǎn)
4. xpath語(yǔ)法-基礎(chǔ)節(jié)點(diǎn)選擇語(yǔ)法
- XPath 使用路徑表達(dá)式來(lái)選取 XML 文檔中的節(jié)點(diǎn)或者節(jié)點(diǎn)集。
- 這些路徑表達(dá)式和我們?cè)诔R?guī)的電腦文件系統(tǒng)中看到的表達(dá)式非常相似。
- 使用chrome插件選擇標(biāo)簽時(shí)候,選中時(shí),選中的標(biāo)簽會(huì)添加屬性class="xh-highlight"
4.1 xpath定位節(jié)點(diǎn)以及提取屬性或文本內(nèi)容的語(yǔ)法
| 表達(dá)式 | 描述 |
|---|---|
| nodename | 選中該元素。 |
| / | 從根節(jié)點(diǎn)選取、或者是元素和元素間的過(guò)渡。 |
| // | 從匹配選擇的當(dāng)前節(jié)點(diǎn)選擇文檔中的節(jié)點(diǎn),而不考慮它們的位置。 |
| . | 選取當(dāng)前節(jié)點(diǎn)。 |
| .. | 選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)。 |
| @ | 選取屬性。 |
| text() | 選取文本。 |
4.2 語(yǔ)法練習(xí)
接下來(lái)我們通過(guò)itcast的頁(yè)面來(lái)練習(xí)上述語(yǔ)法:http://www.itcast.cn/
- 選擇所有的h2下的文本
//h2/text()
- 獲取所有的a標(biāo)簽的href
//a/@href
- 獲取html下的head下的title的文本
/html/head/title/text()
- 獲取html下的head下的link標(biāo)簽的href
/html/head/link/@href
知識(shí)點(diǎn):掌握 xpath語(yǔ)法-選取節(jié)點(diǎn)以及提取屬性或文本內(nèi)容的語(yǔ)法
5. xpath語(yǔ)法-節(jié)點(diǎn)修飾語(yǔ)法
可以根據(jù)標(biāo)簽的屬性值、下標(biāo)等來(lái)獲取特定的節(jié)點(diǎn)
5.1 節(jié)點(diǎn)修飾語(yǔ)法
| 路徑表達(dá)式 | 結(jié)果 |
|---|---|
| //title[@lang="eng"] | 選擇lang屬性值為eng的所有title元素 |
| /bookstore/book[1] | 選取屬于 bookstore 子元素的第一個(gè) book 元素。 |
| /bookstore/book[last()] | 選取屬于 bookstore 子元素的最后一個(gè) book 元素。 |
| /bookstore/book[last()-1] | 選取屬于 bookstore 子元素的倒數(shù)第二個(gè) book 元素。 |
| /bookstore/book[position()>1] | 選擇bookstore下面的book元素,從第二個(gè)開(kāi)始選擇 |
| //book/title[text()='Harry Potter'] | 選擇所有book下的title元素,僅僅選擇文本為Harry Potter的title元素 |
| /bookstore/book[price>35.00]/title | 選取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值須大于 35.00。 |
5.2 關(guān)于xpath的下標(biāo)
- 在xpath中,第一個(gè)元素的位置是1
- 最后一個(gè)元素的位置是last()
- 倒數(shù)第二個(gè)是last()-1
5.3 語(yǔ)法練習(xí)
從itcast的頁(yè)面中,選擇所有學(xué)科的名稱、第一個(gè)學(xué)科的鏈接、最后一個(gè)學(xué)科的鏈接:http://www.itcast.cn/
- 所有的學(xué)科的名稱
//div[@class="nav_txt"]//a[@class="a_gd"]
- 第一個(gè)學(xué)科的鏈接
//div[@class="nav_txt"]/ul/li[1]/a/@href
- 最后一個(gè)學(xué)科的鏈接
//div[@class="nav_txt"]/ul/li[last()]/a/@href
知識(shí)點(diǎn):掌握 xpath語(yǔ)法-選取特定節(jié)點(diǎn)的語(yǔ)法
6. xpath語(yǔ)法-其他常用節(jié)點(diǎn)選擇語(yǔ)法
可以通過(guò)通配符來(lái)選取未知的html、xml的元素
6.1 選取未知節(jié)點(diǎn)的語(yǔ)法
| 通配符 | 描述 |
|---|---|
| * | 匹配任何元素節(jié)點(diǎn)。 |
| node() | 匹配任何類型的節(jié)點(diǎn)。 |
6.2 語(yǔ)法練習(xí)
從itcast的頁(yè)面中 http://www.itcast.cn/ ,選中全部的標(biāo)簽、全部的屬性
- 全部的標(biāo)簽
//*
- 全部的屬性
//node()
知識(shí)點(diǎn):掌握 xpath語(yǔ)法-選取位置節(jié)點(diǎn)的語(yǔ)法
7. lxml模塊的安裝與使用示例
lxml模塊是一個(gè)第三方模塊,安裝之后使用
7.1 lxml模塊的安裝
對(duì)發(fā)送請(qǐng)求獲取的xml或html形式的響應(yīng)內(nèi)容進(jìn)行提取
pip/pip3 install lxml
知識(shí)點(diǎn):了解 lxml模塊的安裝
7.2 爬蟲(chóng)對(duì)html提取的內(nèi)容
- 提取標(biāo)簽中的文本內(nèi)容
- 提取標(biāo)簽中的屬性的值
- 比如,提取a標(biāo)簽中href屬性的值,獲取url,進(jìn)而繼續(xù)發(fā)起請(qǐng)求
7.3 lxml模塊的使用
-
導(dǎo)入lxml 的 etree 庫(kù)
from lxml import etree -
利用etree.HTML,將html字符串(bytes類型或str類型)轉(zhuǎn)化為Element對(duì)象,Element對(duì)象具有xpath的方法,返回結(jié)果的列表
html = etree.HTML(text) ret_list = html.xpath("xpath語(yǔ)法規(guī)則字符串") -
xpath方法返回列表的三種情況
- 返回空列表:根據(jù)xpath語(yǔ)法規(guī)則字符串,沒(méi)有定位到任何元素
- 返回由字符串構(gòu)成的列表:xpath字符串規(guī)則匹配的一定是文本內(nèi)容或某屬性的值
- 返回由Element對(duì)象構(gòu)成的列表:xpath規(guī)則字符串匹配的是標(biāo)簽,列表中的Element對(duì)象可以繼續(xù)進(jìn)行xpath
7.4 lxml模塊使用示例
運(yùn)行下面的代碼,查看打印的結(jié)果
from lxml import etree
text = '''
<div>
<ul>
<li class="item-1">
<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>
</ul>
</div>
'''
html = etree.HTML(text)
#獲取href的列表和title的列表
href_list = html.xpath("http://li[@class='item-1']/a/@href")
title_list = html.xpath("http://li[@class='item-1']/a/text()")
#組裝成字典
for href in href_list:
item = {}
item["href"] = href
item["title"] = title_list[href_list.index(href)]
print(item)
8 練習(xí)
爬取百度貼吧內(nèi)任意吧的帖子標(biāo)題跟相應(yīng)網(wǎng)址鏈接
-
注意:
- 分頁(yè)
參考代碼
import requests
from lxml import etree
class tieba:
def __init__(self, word):
self.word = word
self.url = "https://tieba.baidu.com/f?kw={}".format(self.word)
print(self.url)
self.headers = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) '
}
def get_data(self, url):
response = requests.get(url, headers = self.headers)
return response.content
def parse_data(self, data):
# 創(chuàng)建element對(duì)象
html = etree.HTML(data)
el_list = html.xpath('//li[@class=" j_thread_list clearfix"]/div/div[2]/div[1]/div[1]/a')
# 檢查是否獲取到
# print(len(el_list))
data_list = []
for i in el_list:
a = {}
a['title'] = i.xpath("./text()")[0]
a['herf'] = 'http://tieba.baidu.com' + i.xpath('./@href')[0]
data_list.append(a)
try:
next_url = 'http:' + html.xpath('//*[contains(text(),"下一頁(yè)>")]/@href')[0]
except:
next_url = None
return data_list, next_url
def save_data(self, data_list):
for data in data_list:
print(data)
def run(self):
#url
next_url = self.url
#headers
while True:
# 發(fā)送列表請(qǐng)求,獲取響應(yīng)
list_page_data = self.get_data(next_url)
# 解析列表頁(yè)面的響應(yīng),提取帖子列表數(shù)據(jù)和下一頁(yè)url
data_list, next_url = self.parse_data(list_page_data)
self.save_data(data_list)
# 翻頁(yè)&循環(huán)終止條件
if next_url == None:
break
if __name__ == '__main__':
word = input("輸入想要爬取的貼吧名稱:")
tieba = tieba(word)
tieba.run()
知識(shí)點(diǎn):掌握 lxml模塊中使用xpath語(yǔ)法定位元素提取屬性值或文本內(nèi)容
9. lxml模塊中etree.tostring函數(shù)的使用
運(yùn)行下邊的代碼,觀察對(duì)比html的原字符串和打印輸出的結(jié)果
from lxml import etree
html_str = ''' <div> <ul>
<li class="item-1"><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>
</ul> </div> '''
html = etree.HTML(html_str)
handeled_html_str = etree.tostring(html).decode()
print(handeled_html_str)
9.1 現(xiàn)象和結(jié)論
打印結(jié)果和原來(lái)相比:
- 自動(dòng)補(bǔ)全原本缺失的
li標(biāo)簽- 自動(dòng)補(bǔ)全
html等標(biāo)簽
<html><body><div> <ul>
<li class="item-1"><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>
結(jié)論:
lxml.etree.HTML(html_str)可以自動(dòng)補(bǔ)全標(biāo)簽
lxml.etree.tostring函數(shù)可以將轉(zhuǎn)換為Element對(duì)象再轉(zhuǎn)換回html字符串爬蟲(chóng)如果使用lxml來(lái)提取數(shù)據(jù),應(yīng)該以
lxml.etree.tostring的返回結(jié)果作為提取數(shù)據(jù)的依據(jù)