一、子產品介紹以及安裝
xpath是一個html元素選擇器,這個子產品是存在lxml庫中,安裝lxml庫後就可以直接使用xpath
pip install lxml
二、Xpath術語
節點
在 XPath 中,有七種類型的節點:元素、屬性、文本、命名空間、處理指令、注釋以及文檔(根)節點。XML 文檔是被作為節點樹來對待的。樹的根被稱為文檔節點或者根節點
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
</bookstore>
用以上的文檔來說明其中的節點
<bookstore> (文檔節點)
<author>J K. Rowling</author> (元素節點)
(屬性節點)
基本值
J K. Rowling就是基本值,其無法再被拆分
節點之間的關系
<book>
<title>Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
-
父:每個元素以及屬性都有一個父
這個文檔中book是title,author,year,price的父元素
-
子:元素節點可有零個、一個或多個子
上述例子中title等就是book的子元素
-
同胞:擁有相同的父的節點
title、author、year 以及 price 元素都是同胞
- 先輩:某節點的父、父的父,等等
- 後輩
三、Xpath文法
選取節點
表達式 | 描述 |
---|---|
nodename | 選取此節點的所有子節點 |
bookstore | 選取 bookstore 元素的所有子節點 |
/ | 從根節點選取 |
/bookstore | 選取根元素 bookstore |
bookstore/book | 選取屬于 bookstore 的子元素的所有 book 元素 |
// | 從比對選擇的目前節點選擇文檔中的節點,而不考慮它們的位置 |
//book | 選取所有 book 子元素,而不管它們在文檔中的位置 |
bookstore//book | 選擇屬于 bookstore 元素的後代的所有 book 元素,而不管它們位于 bookstore 之下的什麼位置 |
//@lang | 選取名為 lang 的所有屬性 |
謂語
謂語用來查找某個特定的節點或者包含某個指定的值的節點。
謂語被嵌在方括号中
表達式 | 描述 |
---|---|
/bookstore/book[1] | 選取屬于 bookstore 子元素的第一個 book 元素 |
/bookstore/book[last()] | 選取屬于 bookstore 子元素的最後一個 book 元素 |
/bookstore/book[last()-1] | 選取屬于 bookstore 子元素的倒數第二個 book 元素 |
/bookstore/book[position()< 3] | 選取最前面的兩個屬于 bookstore 元素的子元素的 book 元素 |
//title[@lang] | 選取所有擁有名為 lang 的屬性的 title 元素 |
//title[@lang=‘eng’] | 選取所有 title 元素,且這些元素擁有值為 eng 的 lang 屬性 |
/bookstore/book[price>35.00] | 選取 bookstore 元素的所有 book 元素,且其中的 price 元素的值須大于 35.00 |
/bookstore/book[price>35.00]/title | 選取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值須大于 35.00 |
選取未知節點
XPath 通配符可用來選取未知的 XML 元素
表達式 | 描述 |
---|---|
* | 比對任何元素節點 |
@* | 比對任何屬性節點 |
node() | 比對任何類型的節點 |
四、lxml
因為xpath子產品在python3中包含于lxml中,那麼我們也簡要的來描述一下lxml子產品
- 1、導入etree庫
from lxml import tree
- 2、利用etree.HTML,将字元串轉換為Element對象具有xpath的方法,傳回結果的清單,能夠接受byte類型的資料str類型的資料
html = etree.HTML(text)
ret_list = html.xpath("xpath字元串")
五、執行個體
import requests
import lxml.html
import csv
class DouBan():
def __init__(self):
self.url_temp = "https://movie.douban.com/top250?start={}&filter="
self.headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36'}
# 擷取top250的所有html頁面資訊
def get_page_url(self):
url_list = [ self.url_temp.format( i*25 ) for i in range(10)]
return url_list
# 擷取每一部電影詳情頁的url
def get_movie_url(self,url):
resp = requests.get(url,headers=self.headers)
tree = lxml.html.etree.HTML(resp.text)
m_urls = tree.xpath("//li/div/div/a/@href")
#擷取所有li标簽下的div的div的a标簽名為href屬性的值
print(m_urls)
return m_urls
# 擷取每一部電影的詳細資訊
def get_movie_data(self,m_url):
moive_page = requests.get(m_url,headers=self.headers)
parse_movie= lxml.html.etree.HTML(moive_page.text)
#parse_movie = moive_page.content.decode()
return parse_movie
# 擷取每一部電影的評分,地區等詳細資訊
def get_movie_data_details(self,parse_movie):
#排名
ranking = parse_movie.xpath("//span[@class='top250-no']/text()")
#電影名
name = parse_movie.xpath("//h1/span[1]/text()")
print(name)
#評分
score = parse_movie.xpath("//div[@class='rating_self clearfix']/strong/text()")
return zip(ranking, name, score)
# 儲存html網頁資訊
def save_html(self,context,index):
htmlname = "豆瓣電影top250,No.{}.html".format(index)
with open(htmlname,'w') as f:
f.write(context)
# 儲存為csv結構
def save_result(self,data):
with open('douban_top250.csv','a',encoding="utf-8-sig") as fp:
writer = csv.writer(fp)
writer.writerow(data)
def run(self):
#1.擷取url
url_list = self.get_page_url()
for url in url_list:
m_urls = self.get_movie_url(url)
for m_url in m_urls:
parse_movie = self.get_movie_data(m_url)
data = self.get_movie_data_details(parse_movie)
print(data)
self.save_result(data)
#2、擷取相應
#3、提取資料
if __name__ == "__main__":
douban = DouBan()
douban.run()
這是top250網頁的一段源代碼
"//li/div/div/a/@href"
#擷取每一個電影詳情頁的url
<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://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class="">
</a>
//div[@class='rating_self clearfix']/strong/text()
#擷取每部電影的評分
<div class="rating_self clearfix" typeof="v:Rating">
<strong class="ll rating_num" property="v:average">9.7</strong>
<span property="v:best" content="10.0"></span>
<div class="rating_right ">
<div class="ll bigstar bigstar50"></div>
<div class="rating_sum">
<a href="collections" class="rating_people">
<span property="v:votes">2006192</span>人評價
</a>
</div>
</div>
</div>