python爬蟲:XPath語法和使用示例
阿新 • • 發佈:2020-08-09
# python爬蟲:XPath語法和使用示例
>XPath(XML Path Language)是一門在XML文件中查詢資訊的語言,可以用來在XML文件中對元素和屬性進行遍歷。
## 選取節點
XPath使用路徑表示式來選取XML文件中的節點或者節點集。這些路徑表示式和我們在常規的電腦檔案系統中看到的表示式非常相似。
**常用路徑表示式:**
|表示式|描述|
|---|---|
|nodename|選取此節點的所有子節點。|
|/|從根節點選取。|
|//|從匹配選擇的當前節點選擇文件中的節點,而不考慮它們的位置。|
|.|選取當前節點。|
|..|選取當前父節點。|
|@|選取屬性。|
|text()|選取文字內容。|
**例項**
在下面的表格中,列出一些路徑表示式以及表示式的結果:
|路徑表示式|結果|
|---|---|
|bookstore|選取bookstore元素|
|/bookstore|選取根元素bookstore。註釋:假如路徑起始於(/),則此路徑始終代表到某元素的絕對路徑。|
|bookstore/book|選取屬於bookstore的子元素的所有book元素。|
|//book|選取所有book子元素,而不管他們在文件中的位置。|
|bookstore//book|選擇屬於bookstore元素的後代的所有book元素,而不管它們位於bookstore之下的什麼位置。|
|//book/title/@lang|選擇所有的book下面的title中的lang屬性的值。|
|//book/title/text()|選擇所有的book下面的title的文字。|
## 查詢特定的節點
|路徑表示式|結果|
|---|---|
|//title[@lang]|選取所有擁有名為lang的屬性的title元素。|
|//title[@lang="eng"]|選取lang屬性值為eng的所有title元素。|
|/bookstore/book[1]|選取屬於bookstore子元素的第一個book元素。|
|/bookstore/book[last()]|選取屬於bookstore子元素的最後一個book元素。|
|/bookstore/book[position()>1]|選擇bookstore下面的book元素,從第二個開始選擇。|
|//book/title[text()='Harry Potter']|選擇所有book下的title元素,僅僅選擇文字為Harry Potter的title元素。|
|/bookstore/book[price>35.00]/title|選取bookstore元素中的book元素的所有title元素,且其中的price元素的值需大於35.00。|
注意點:在xpath中,第一個元素的位置是1,最後一個元素的位置是last(),倒數第二個是last()-1。
## 選取未知節點
XPath萬用字元可用來選取未知的XML元素。
|萬用字元|描述|
|---|---|
|*|匹配任何元素節點。|
|@*|匹配任何屬性的節點。|
|node()|匹配任何型別的節點。|
**例項**
在下面的表格中,列出一些路徑表示式以及表示式的結果:
|路徑表示式|結果|
|---|---|
|//bookstore/*|選取bookstore元素的所有子元素。|
|//*|選取文件中的所有元素。|
|//title[@*]|選取所有帶屬性的title元素。|
## 選取若干路徑
通過在路徑表示式中使用"|"運算子,您可以選取若干個路徑。
**例項**
在下面的表格中,列出一些路徑表示式以及表示式的結果:
|路徑表示式|結果|
|---|---|
|//book/title \| //book/price|選取book元素的所有title和price元素。|
|//title \| //price|選取文件中的所有title和price元素。|
|/bookstore/book/title \| //price|選取屬於bookstore元素的book元素的所有title元素,以及文件中所有的price元素。|
## 使用技巧
在一般的爬蟲實戰中,XPath路徑可以通過谷歌瀏覽器或火狐瀏覽器中複製得到,如下圖:
![](https://img2020.cnblogs.com/blog/1878490/202008/1878490-20200809121652472-1735988149.png)
但是對於新手可以多多嘗試自己寫XPath路徑,因為有時候複製獲取的XPath路徑過長,而自己寫的更簡潔寫。
例子:
```python
import requests
from lxml import etree
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
}
url = 'http://www.qiushibaike.com/text/'
res = requests.get(url, headers=headers)
selector = etree.HTML(res.text)
id = selector.xpath('//div[@class="article block untagged mb15 typs_long"]/div[1]/a[2]/h2/text()')
print(''.join(id).strip())
# 注意:通過/text()可以獲取標籤中的文字資訊。
# 結果為:璃白°
```
幾種解析方式的效能對比
|爬取方法|效能|使用難度|
|---|---|---|
|正則表示式|快|困難|
|BeautifulSoup|慢|簡單|
|Lxml|快|簡單|
## 爬取豆瓣圖書TOP250
爬取的例子直接輸出到螢幕。
需求分析:
(1)要爬取的內容為豆瓣圖書top250的資訊,如下圖所示:
![](https://img2020.cnblogs.com/blog/1878490/202008/1878490-20200809121719147-806142894.png)
(2)所爬取的網頁連結:https://book.douban.com/top250?start=0
(3)需要爬取的資訊有:書名,書本的連結,作者,出版社,出版日期評分和評價。
具體程式碼如下:
```python
# -*- encoding:utf8 -*-
# 爬取豆瓣圖書TOP250。
import requests
from lxml import etree
# 請求頭,用來模擬瀏覽器
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
}
def get_info(url):
res = requests.get(url, headers=headers).text
# lxml庫的etree解析html
selector = etree.HTML(res)
# 獲取的是一頁中所有的書本資訊,每本的所以資訊都在類為item的tr下面。
infos = selector.xpath("//tr[@class='item']")
for info in infos:
# 書名
name = info.xpath('td/div/a/@title')[0]
# 書的連結地址
book_url = info.xpath('td/div/a/@href')[0]
# 獲取的是書本的基本資訊,有作者和出版社,和出版日期...
book_infos = info.xpath('td/p/text()')[0]
# 作者
author = book_infos.split('/')[0]
# 出版社
publisher = book_infos.split('/')[-3]
# 出版日期
date = book_infos.split('/')[-2]
# 價格
price = book_infos.split('/')[-1]
# 書本的評分
rate = info.xpath('td/div/span[2]/text()')[0]
# 下面的評論
comments = info.xpath('td/p/span/text()')
# 這裡單行的if語句是:如果comments的長度不為0時,則把comments的第1個元素給comment,否則就把"空"賦值給comment
comment = comments[0] if len(comments) != 0 else "空"
print(name + " " + book_url + " " + book_infos + " " + author + " " + publisher + " " + date + " " + price + " " + rate + " " + comment)
print()
# 獲取下一頁的url
if selector.xpath("//span[@class='next']/a"):
next_pag = selector.xpath("//span[@class='next']/a/@href")
get_info(''.join(next_pag))
if __name__ == "__main__":
url = 'https://book.douban.com/top250'
get_info(url)
```
部分結果如下圖所示:
![](https://img2020.cnblogs.com/blog/1878490/202008/1878490-20200809121730696-1944582795.png)