1. 程式人生 > >一起學爬蟲——使用xpath庫爬取貓眼電影國內票房榜

一起學爬蟲——使用xpath庫爬取貓眼電影國內票房榜

之前分享了一篇使用requests庫爬取豆瓣電影250的文章,今天繼續分享使用xpath爬取貓眼電影熱播口碑榜

XPATH語法
XPATH(XML Path Language)是一門用於從XML檔案中查詢資訊的語言。通用適用於從HTML檔案中查詢資料。工欲善其事必先利其器,我們首先來了解XPATH常用的語法規則。

常用匹配規則:
| 屬性 | 匹配規則描述|
|-------|------|
| nodename| 匹配此節點的所有子節點 |
|/|匹配當前節點的直接子節點,不包含孫節點|
|//|匹配當前節點的所有子孫節點|
|.|匹配當前節點|
|..|匹配當前節點的父節點|
|@|匹配屬性值|

XPATH的匹配功能很強大,上面6種匹配規則可以搭配使用,通過上面的6種匹配規則即可爬取到網頁上所有的我們想要的資料。

使用下面的HTML文件介紹上述6種規則的搭配使用。

<html>
    <div id="div_id1" class="div_class1">
        <ul>
            <li class="li_item1"><a href="www.bigdata17.com">Summer哥的自留地</a></li>
            <li class="li_item2 li"><a href="li_test.html">test li</a></li>
        </ul>
            <li>20</li>
            <li>30</li>
        <ul>
        </ul>
    </div>
</html>
匹配表示式 結果
//* 匹配網頁中所有的節點
//div 匹配所有div節點
//div/li 匹配所有div節點的所有li節點
//a[@href="www.bigdata17.com"/..] 匹配href屬性為www.bigdata17.com的A節點的父節點
//li[@class="li_item1"] 匹配所有li元素,且為class屬性為"li_item1"
//li[@class] 匹配所有擁有class屬性的li元素
//li/a/@href 獲取所有li元素a子元素的href屬性值,注意和//li[@class="li_item1"的且
//li//text() 過去li節點所有子節點的文字
//li[@class="li_item1"]/a/text() 獲取class屬性為li_item1的li節點所有a子節點的文字
//li[contains(@class,"li")]/a/text() 獲取class屬性值包含li的li節點所有a子節點的文字
//div[contains(@class,"div") and @id="div_id1"]/ul 獲取所有class屬性包含“div”且id屬性值為“div_id1”的div節點的ul子節點
/div/ul[li>20] 選取div節點的所有 ul節點,且其中的li節點的值須大於20
/div/ul[1] 匹配屬於div節點的第一個 ul節點。
/div/ul[last()] 匹配屬於div 子節點的最後一個ul節點
/div/ul[last()-1] 匹配屬於div 子節點的倒數第二個ul節點
/div/ul[position() < 3] 匹配最前面的兩個屬於div元素的ul子元素

通過上面的匹配規則,我們就可以使用XPATH來解析爬取貓眼電影國內票房榜的資料。

XPATH要配合requests一起使用,使用requests抓取網頁資訊,然後使用XPATH解析網頁資訊,XPATH在lxml庫中,因此需要在pycharm中安裝lxml。

1、獲取取貓眼電影熱播口碑榜HTML檔案
下面是抓取貓眼電影熱播口碑榜的程式碼:

from lxml import etree
import requests

url = 'http://maoyan.com/board/1'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}

response = requests.get(url,headers=headers)
html = response.text

2、提取電影名
現在瀏覽器的開發者工具都支援提取xpath規則,具體步驟如下:
首先在瀏覽器中開啟網址,按下F12,ctrl+f查詢電影名,滑鼠右鍵彈出的選單,點選Copy選項,點選Copy Xpath。到此就可以把電影名稱的xpath匹配規則提取出來:
python xpath

電影名稱提取的規則是:
//*[@id="app"]/div/div/div/dl/dd[1]/div/div/div[1]/p[1]/a

我們使用這個規則看下是否能提取出電影名稱,程式碼如下:

from lxml import etree
import requests

url = 'http://maoyan.com/board/7'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}

response = requests.get(url,headers=headers)
html = response.text

movie_name_xpath = '//*[@id="app"]/div/div/div/dl/dd[1]/div/div/div[1]/p[1]/a/text()'
s = etree.HTML(html)
movie_name = s.xpath(movie_name_xpath)
print(movie_name)

執行結果:[<Element a at 0x35f5248>]
上面的結果顯示抓取到的是a元素,就是html中的a標籤,要想獲取該元素中的文字值,必須在xpath匹配規則追加/text(),下面是追加/text()後的程式碼及執行結果:

from lxml import etree
import requests

url = 'http://maoyan.com/board/1'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}

response = requests.get(url,headers=headers)
html = response.text

movie_name_xpath = '//*[@id="app"]/div/div/div/dl/dd[1]/div/div/div[1]/p[1]/a/text()'
s = etree.HTML(html)
movie_name = s.xpath(movie_name_xpath)
print(movie_name)

執行結果['嗝嗝老師']

這裡只是提取一部電影的名稱,我們要想提取當前網頁的所有電影的名稱,匹配規則怎麼寫呢?
下面是當前頁10部電影的xpath匹配規則

//*[@id="app"]/div/div/div/dl/dd[1]/div/div/div[1]/p[1]/a
//*[@id="app"]/div/div/div/dl/dd[2]/div/div/div[1]/p[1]/a
//*[@id="app"]/div/div/div/dl/dd[3]/div/div/div[1]/p[1]/a
//*[@id="app"]/div/div/div/dl/dd[4]/div/div/div[1]/p[1]/a
//*[@id="app"]/div/div/div/dl/dd[5]/div/div/div[1]/p[1]/a
//*[@id="app"]/div/div/div/dl/dd[6]/div/div/div[1]/p[1]/a
//*[@id="app"]/div/div/div/dl/dd[7]/div/div/div[1]/p[1]/a
//*[@id="app"]/div/div/div/dl/dd[8]/div/div/div[1]/p[1]/a
//*[@id="app"]/div/div/div/dl/dd[9]/div/div/div[1]/p[1]/a
//*[@id="app"]/div/div/div/dl/dd[10]/div/div/div[1]/p[1]/a

發現dd的數字會變化,其他的都不變,因此用萬用字元“*”代替dd節點中的數字,提取當前頁所有電影名字的xpath規則為:

//*[@id="app"]/div/div/div/dl/dd[*]/div/div/div[1]/p[1]/a

看下最後的執行結果是什麼。

from lxml import etree
import requests

url = 'http://maoyan.com/board/1'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}

response = requests.get(url,headers=headers)
html = response.text

movie_name_xpath = '//*[@id="app"]/div/div/div/dl/dd[*]/div/div/div[1]/p[1]/a/text()'
s = etree.HTML(html)
movie_name = s.xpath(movie_name_xpath)
print(movie_name)

執行結果:['嗝嗝老師', '毒液:致命守護者', '無名之輩', '恐龍王', '流浪貓鮑勃', '無雙', '名偵探柯南:零的執行人', '颶風奇劫', '影', '你好,之華']

可見使用萬用字元*把所有的電影名稱都提取出來了。

3、提取電影圖片連結
通過上步驟獲取圖片的xpath匹配規則為:

//*[@id="app"]/div/div/div/dl/dd[1]/a/img[2]

通過開發者工具知道img節點有三個屬性,分別是alt,class和src。
python xpath
其中src的是圖片的地址,在xpath提取規則追加上@src,變為:

//*[@id="app"]/div/div/div/dl/dd[1]/a/img[2]/@src

看下這個xpath規則是否能提取到圖片的連結地址:

from lxml import etree
import requests

url = 'http://maoyan.com/board/7'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}

response = requests.get(url,headers=headers)
html = response.text

movie_img_xpath = '//*[@id="app"]/div/div/div/dl/dd[1]/a/img[2]/@src'
s = etree.HTML(html)
movie_img = s.xpath(movie_img_xpath)
print(movie_img)

執行的結果是:[]

怎麼會得不到src屬性的值呢?難道src屬性不存在?

通過滑鼠右鍵檢視網頁原始檔:
python xpath
原來src變成了data-src。修改xpath規則後看下能否提取出電影圖片連結:

from lxml import etree
import requests

url = 'http://maoyan.com/board/7'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}

response = requests.get(url,headers=headers)
html = response.text

movie_img_xpath = '//*[@id="app"]/div/div/div/dl/dd[1]/a/img[2]/@data-src'
s = etree.HTML(html)
movie_img = s.xpath(movie_img_xpath)
print(movie_img)

執行結果:

['http://p0.meituan.net/movie/[email protected]_220h_1e_1c']

電影圖片連結提取成功。
這是提取一部電影的xpath規則,下面是當前頁面10部電影圖片的規則:

//*[@id="app"]/div/div/div/dl/dd[1]/a/img[2]/@data-src
//*[@id="app"]/div/div/div/dl/dd[2]/a/img[2]/@data-src
//*[@id="app"]/div/div/div/dl/dd[3]/a/img[2]/@data-src
...
...
...
//*[@id="app"]/div/div/div/dl/dd[9]/a/img[2]/@data-src
//*[@id="app"]/div/div/div/dl/dd[10]/a/img[2]/@data-src

觀察發現dd的數字會變化,其他的都不變,因此用萬用字元“*”代替dd節點中的數字,提取當前頁所有電影圖片連結的xpath規則為:

//*[@id="app"]/div/div/div/dl/dd[*]/a/img[2]/@data-src

以此類推,通過上面的方式提取出當前頁所有電影名稱,圖片地址,主演,上映時間,評分的xpath匹配規則:

movie_name_xpath = '//*[@id="app"]/div/div/div/dl/dd[*]/div/div/div[1]/p[1]/a/text()'
movie_img_xpath = '//*[@id="app"]/div/div/div/dl/dd[*]/a/img[2]/@data-src'
movie_actor_xpath = '//*[@id="app"]/div/div/div/dl/dd[*]/div/div/div[1]/p[2]/text()'
movie_release_time_xpath = '//*[@id="app"]/div/div/div/dl/dd[*]/div/div/div[1]/p[3]/text()'
movie_score_xpath = 
'//*[@id="app"]/div/div/div/dl/dd[*]/div/div/div[2]/p/i/text()'

爬取貓眼電影國內熱播榜的完整程式碼如下:

# coding:utf-8
from lxml import etree
import requests

#獲取網頁
def getHtml(url):
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}

    response = requests.get(url,headers=headers)
    html = response.text
    return html
    #
    # movie_img_xpath = '//*[@id="app"]/div/div/div/dl/dd[1]/div/div/div[2]/p/i/text()'
    # s = etree.HTML(html)
    # movie_img = s.xpath(movie_img_xpath)
    # print(movie_img)

#解析網頁
def parseHtml(html):
    s = etree.HTML(html)
    movie_name_xpath = '//*[@id="app"]/div/div/div/dl/dd[*]/div/div/div[1]/p[1]/a/text()'
    movie_img_xpath = '//*[@id="app"]/div/div/div/dl/dd[*]/a/img[2]/@data-src'
    movie_actor_xpath = '//*[@id="app"]/div/div/div/dl/dd[*]/div/div/div[1]/p[2]/text()'
    movie_release_time_xpath = '//*[@id="app"]/div/div/div/dl/dd[*]/div/div/div[1]/p[3]/text()'
    movie_score_xpath = '//*[@id="app"]/div/div/div/dl/dd[*]/div/div/div[2]/p/i/text()'

    movie_name = s.xpath(movie_name_xpath)
    movie_img = s.xpath(movie_img_xpath)
    movie_actor = s.xpath(movie_actor_xpath)
    movie_score = s.xpath(movie_score_xpath)
    movie_release_time = s.xpath(movie_release_time_xpath)

    for i in range(len(movie_name)):
        print('電影名稱:' + movie_name[i])
        print('主演:' + movie_actor[i].strip())
        print('圖片連結:' + movie_img[i].strip())
        print('評分:' + movie_score[2*i] + movie_score[2*i + 1])
        print(movie_release_time[i])
        print('-------------------------------------------強力分割線-------------------------------------------')
def main():
    url = 'http://maoyan.com/board/7'
    html = getHtml(url)
    parseHtml(html)

if __name__ == '__main__':
    main()

總結:
在使用開發者工具提取xpath規則獲取不到相應的資料時,要注意xpath規則是否準確,有些瀏覽器會加上一些多餘的標籤,或者將節點的屬性名改掉,例如上面例子中將的img節點的src屬性變為data-src。結合檢視原始檔都可以獲取到正確的xpath規則。

https://blog.csdn.net/qq_42044484/article/details/80523164