天天看點

python爬蟲常用子產品-xpath以及lxml一、子產品介紹以及安裝二、Xpath術語三、Xpath文法四、lxml五、執行個體

一、子產品介紹以及安裝

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>