介紹
XPath是一種XML路徑語言,被用於在XML文檔中通過元素和屬性進行導航
安裝
pip install lxml
使用
html示例內容,下面的所有練習全都來自與此段示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
<style>
.color1 {
color: red;
text-decoration: none;
}
.color2 {
color: blue;
}
#color3 {
color: pink;
text-decoration: none;
}
</style>
</head>
<body>
<p>this is a text</p>
<span class="color1">
<p>this is a span</p>
</span>
<div>
<p>this is a list</p>
<ul>
<li><a href="#" class="color1">北京</a></li>
<li><a href="#" id="color3">上海</a></li>
<li><a href="#" class="color2">廣州</a></li>
<li><a href="https://www.dogfei.cn">西二旗</a></li>
</ul>
</div>
</body>
</html>
讀取html內容
from lxml import etree
with open('test.html', 'r', encoding='utf-8') as fr:
html = fr.read()
et = etree.HTML(html)
下面就接着這個代碼段往下寫。
所有節點、父節點、子孫節點
所有節點是通過指定'//*'來獲取,例如
et.xpath('//*')
返回如下:
[<Element html at 0x173aa409e88>, <Element head at 0x173aa540788>, <Element meta at 0x173aa5407c8>, <Element title at 0x173aa540848>, <Element style at 0x173aa540a48>, <Element body at 0x173aa540a88>, <Element p at 0x173aa540b08>, <Element div at 0x173aa540b48>, <Element p at 0x173aa540b88>, <Element ul at 0x173aa540948>, <Element li at 0x173aa540bc8>, <Element a at 0x173aa540c08>, <Element li at 0x173aa540c48>, <Element a at 0x173aa540c88>, <Element li at 0x173aa540cc8>, <Element a at 0x173aa540d08>, <Element li at 0x173aa540d48>, <Element a at 0x173aa540d88>]
子孫結點是通過'//'來獲取
# 獲取所有的li節點
et.xpath('//li')
父節點是通過'..'來獲取,有點像linux的..上級目錄
et.xpath('//p/../@class')
結果為
['color1']
獲取文本text()
res0 = et.xpath('//body/p/text()')
返回結果
['this is a text']
獲取指定標簽下的內容
res1 = et.xpath('//li[1]/a/text()')
print(res1)
返回結果
['北京']
指定具體的標簽
res2 = et.xpath('//div/p/')
print(res2)
返回內容
[<Element p at 0x23b49990888>]
指定類選擇器
res3 = et.xpath('//li/a[@class="color2"]/text()')
print(res3)
返回結果
['廣州']
指定id選擇器
res4 = et.xpath('//li/a[@id="color3"]/text()')
print(res4)
返回結果
['上海']
模糊匹配
res5 = et.xpath('//li/a[contains(@href, "http")]/text()')
print(res5)
返回結果
['西二旗']
指定某個屬性的具體值
res6 = et.xpath('//li/a[@href="https://www.dogfei.cn"]/text()')
print(res6)
返回結果
['西二旗']
獲取指定位置的內容
res7 = et.xpath('//li[last()]/a/text()')
print(res7)
返回結果
['西二旗']
也可以用[last() - 1]
還可以使用position()
res8 = et.xpath('//li[position() < 3]/a/text()')
print(res8)
返回結果
['北京', '上海']
通過使用position()
可以獲取到一組數據
通配符
res9 = et.xpath('//li/*/text()') # *也可以省略
print(res9)
返回結果
['北京', '上海', '廣州', '西二旗']
指定所有屬性
res10 = et.xpath('//li//a[@*]/text()')
print(res10)
返回結果
['北京', '上海', '廣州', '西二旗']
使用./
再次查找
res11 = et.xpath('//li')
for i in res11:
r = i.xpath('./a/text()')[0]
print(r)
返回結果
北京
上海
廣州
西二旗
實戰案例
此案例簡單來爬取豆瓣電影的top250,只拿第一頁的數據,打印出排名和電影名,重點是來掌握xpath
的用法
豆瓣電影top250的訪問地址為:https://movie.douban.com/top250
查看頁面源代碼或者瀏覽器f12
查看頁面元素定位到標簽位置,打開其中一段分析來看:
<ol class="grid_view">
<li>
<div class="item">
<div class="pic">
<em class="">1</em>
<a href="https://movie.douban.com/subject/1292052/">
<img width="100" alt="肖申克的救贖"
src="https://img2.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp"
class="">
</a>
</div>
<div class="info">
<div class="hd">
<a href="https://movie.douban.com/subject/1292052/" class="">
<span class="title">肖申克的救贖</span>
<span class="title"> / The Shawshank Redemption</span>
<span class="other"> / 月黑高飛(港) / 刺激1995(台)</span>
</a>
<span class="playable">[可播放]</span>
</div>
<div class="bd">
<p class="">
導演: 弗蘭克·德拉邦特 Frank Darabont 主演: 蒂姆·羅賓斯 Tim Robbins /...<br>
1994 / 美國 / 犯罪 劇情
</p>
<div class="star">
<span class="rating5-t"></span>
<span class="rating_num" property="v:average">9.7</span>
<span property="v:best" content="10.0"></span>
<span>2468198人評價</span>
</div>
<p class="quote">
<span class="inq">希望讓人自由。</span>
</p>
</div>
</div>
</div>
</li>
.....
.....
.....
.....
</ol>
-
可以看到電影都在
ol
這個有序標簽內,ol
標簽中的類屬性值grid_view
這個是惟一的,直接用xpath
,通過類選擇器來拿到這段html,然后再進一步處理。 -
由於這里是一個列表,所以得需要進行遍歷,既然是遍歷,那就應該拿到所有的
li
標簽下的內容,然后遍歷 -
每遍歷一次列表,就會拿到每一個電影的信息,然后可以找到排名信息是在
em
標簽下,電影名稱是在第一個span
標簽下
from lxml import etree
import requests
def get_resource_html(url):
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"
}
res = requests.get(url, headers=headers).text
res.encode('utf-8')
return res
def parse_html(html):
et = etree.HTML(html)
movie_list = et.xpath('//ol[@class="grid_view"]/li')
for movie in movie_list:
movie_ranking = movie.xpath('.//div[@class="pic"]/em/text()')[0]
movie_title = movie.xpath('.//div[@class="info"]//span[1]/text()')[0]
with open('movie.csv', 'a+', encoding='utf-8') as fw:
fw.write(f"{movie_ranking},{movie_title}\n")
return
def main():
url = "https://movie.douban.com/top250"
html = get_resource_html(url)
parse_html(html)
if __name__ == '__main__':
main()
執行結果
歡迎各位朋友關注我的公眾號,來一起學習進步哦