一起學爬蟲——使用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/36f1a50b4eae6aa93e3f7a373fb6ee89991083.jpg@160w_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規則。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM