爬蟲入門經典(四) | 如何爬取豆瓣電影Top250

2020-10-22 15:00:32

  大家好,我是不溫卜火,是一名計算機學院巨量資料專業大三的學生,暱稱來源於成語—不溫不火,本意是希望自己性情溫和。作為一名網際網路行業的小白,博主寫部落格一方面是為了記錄自己的學習過程,另一方面是總結自己所犯的錯誤希望能夠幫助到很多和自己一樣處於起步階段的萌新。但由於水平有限,部落格中難免會有一些錯誤出現,有紕漏之處懇請各位大佬不吝賜教!暫時只在csdn這一個平臺進行更新,部落格主頁:https://buwenbuhuo.blog.csdn.net/
1

PS:由於現在越來越多的人未經本人同意直接爬取博主本人文章,博主在此特別宣告:未經本人允許,禁止轉載!!!


2


  博主早期其實寫過一篇爬取豆瓣電影Top250的博文,當時由於剛開始學習,使用了urllib庫進行爬取。現在看來,顯的過於臃餘。因此本片博文,博主帶來了較為簡潔的寫法。使用xpath進行解,不得不說真香!!!
3
  如果想看博主剛開始寫的粗劣寫法,博主在此給出傳送門:爬取豆瓣電影詳細資料,儲存為CSV檔案

🆗,話不多說。進入正題。

一、專案分析

1.1 單頁分析

目標網站:https://movie.douban.com/top250
4

我們開啟網址,檢視頁面佈局,可以看到有電影名稱及別名、評分、引言等等,在此就以電影名稱及別名、評分、引言為爬取目標。

我們開啟開發者選項,發現這個網頁為靜態網頁,這樣就很好爬取了:
5

爬取部分所在位置
6

1、電影名稱與其他名稱
7
2、 URL
8
3、 評分
9
4、 引言
10
11
這個時候,你是否會感覺無從下手。沒關係,本大師會為你排憂解惑!
12
網頁大體結構已經分析完成,那麼接下來就需要對我們所要爬取的內容進行xpath解析:

1、 電影名稱解析
13
2、 其他名稱解析
14
3、 連結解析
15
通過檢視我們發現得到的是這一頁中的所有連結,我們選取第一個即:

(//div[@class="hd"]/a/@href)[0]

這樣就可以達到對應的URL連結了。

4、 評分解析
16
我們可以看到評分和連結一樣,都是選取第一個即可:

(//div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text())[0]

5、 引言解析
17
引言解析和上述兩個看著一樣,但是如果直接和上面以上是會報錯的,因為引言可能有的是沒有的,比如說排名212的《九品芝麻官》,就沒有引言。
18
這個時候就需要加上判斷語句:

# 條件語句:如果有引言則寫引言,若沒有則不寫
if quote:
    quote = quote[0]
else:
    quote = ''

1.2 翻頁分析

在分析完單頁爬取內容後,我們就需要繼續分析分頁,來完成迴圈爬取的功能。
19
我們先來分析下網頁連結:

https://movie.douban.com/top250?start=0&filter=
https://movie.douban.com/top250?start=25&filter=
https://movie.douban.com/top250?start=50&filter=

通過檢視對比,我們發現其網頁變化僅為start=?以此可以判定,其是以25為分頁。

我們再來看下總頁數,這印證了我們的猜想是正確的。
20
分析完成了下面就可以來進行實現了:

doubanUrl = 'https://movie.douban.com/top250?start={}&filter='

# 一共10頁,迴圈10次
for i in range(10):
    # 獲取url
    pageLink = doubanUrl.format(i * 25)
    print(pageLink)

下面我們來列印下拼接網址
21
開啟其中一個網址,看是否成功
22
Respect,🆗分析到這裡就完美結束了!

23

二、完整程式碼

# encoding: utf-8
'''
  @author 李華鑫
  @create 2020-10-14 8:30
  Mycsdn:https://buwenbuhuo.blog.csdn.net/
  @contact: 459804692@qq.com
  @software: Pycharm
  @file: 豆瓣.py
  @Version:1.0
  
'''
import requests
from lxml import etree
import csv

# 豆瓣top250網址
doubanUrl = 'https://movie.douban.com/top250?start={}&filter='


# 獲取網頁原始碼
def getSource(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
    }
    response = requests.get(url, headers=headers)
    # 以防出現亂碼 設定編碼格式
    response.encoding = 'utf-8'
    return response.text


# 引言 評分 網址 標題 ---> 網頁原始碼中
# 獲取電影資訊
def getEveryItem(source):
    # 生成一個Html物件
    selector = etree.HTML(source)
    # 通過selector物件來找到  電影資訊
    movieItemList = selector.xpath('//div[@class="info"]')

    # 定義一個空列表
    movieList = []

    # 通過for迴圈來遍歷
    for eachMovie in movieItemList:
        # 建立一個字典,向列表中儲存資料[{電影一},{電影二}...]
        movieDict = {}

        title = eachMovie.xpath('div[@class="hd"]/a/span[@class="title"]/text()') # 電影名
        otherTitle = eachMovie.xpath('div[@class="hd"]/a/span[@class="other"]/text()')  # 其他名稱
        link = eachMovie.xpath('div[@class="hd"]/a/@href')[0]  # 連結
        star = eachMovie.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()')[0]  # 評分
        quote = eachMovie.xpath('div[@class="bd"]/p[@class="quote"]/span/text()')  # 引言

        # 條件語句:如果有引言則寫引言,若沒有則不寫
        if quote:
            quote = quote[0]
        else:
            quote = ''

        # 儲存資料
        movieDict['title'] = ''.join(title + otherTitle)
        movieDict['url'] = link
        movieDict['star'] = star
        movieDict['quote'] = quote
        print(movieDict)

        movieList.append(movieDict)

    return movieList


# 儲存資料
def writeData(movieList):
    with open('douban_top250.csv', 'w', encoding='utf-8',newline='') as f:
        writer = csv.DictWriter(f, fieldnames=['title', 'star', 'quote', 'url'])
        writer.writeheader()  # 寫入表頭
        for each in movieList:
            # 逐行寫入
            writer.writerow(each)


# 啟動
if __name__ == "__main__":
    movieList = []

    # 一共10頁,迴圈10次
    for i in range(10):
        # 獲取url
        pageLink = doubanUrl.format(i * 25)
        print(pageLink)
        source = getSource(pageLink)
        movieList += getEveryItem(source)

    writeData(movieList)

三、執行結果

24
25
美好的日子總是短暫的,雖然還想繼續與大家暢談,但是本篇博文到此已經結束了,如果還嫌不夠過癮,不用擔心,我們下篇見!


12

  好書不厭讀百回,熟讀課思子自知。而我想要成為全場最靚的仔,就必須堅持通過學習來獲取更多知識,用知識改變命運,用部落格見證成長,用行動證明我在努力。
  如果我的部落格對你有幫助、如果你喜歡我的部落格內容,請「點贊」 「評論」「收藏」一鍵三連哦!聽說點讚的人運氣不會太差,每一天都會元氣滿滿呦!如果實在要白嫖的話,那祝你開心每一天,歡迎常來我部落格看看。
  碼字不易,大家的支援就是我堅持下去的動力。點贊後不要忘了關注我哦!

21
22