一起學爬蟲——使用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匹配規則提取出來:

電影名稱提取的規則是:
//*[@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。

其中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屬性不存在?
通過滑鼠右鍵檢視網頁原始檔:

原來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規則。
https://blog.csdn.net/qq_42044484/article/details/80523164