天天看點

爬蟲執行個體——爬取豆瓣網 top250 電影的資訊

本節通過一個具體的執行個體來看下編寫爬蟲的具體過程。以爬取豆瓣網 top250 電影的資訊為例,top250 電影的網址為:​​

​https://movie.douban.com/top250​

​​。在浏覽器的位址欄裡輸入 ​

​https://movie.douban.com/top250​

​,我們會看到如下内容:

爬蟲執行個體——爬取豆瓣網 top250 電影的資訊

對于每一部電影需要爬取的内容如下圖所示:

爬蟲執行個體——爬取豆瓣網 top250 電影的資訊

如上圖所示,爬取的内容包括電影排名、電影名稱、電影評分、電影屬于哪個國家、電影類型、電影的上映時間以及電影的導演、主演。了解了要爬取哪些内容之後,接下來需要知道這些内容對應的 html 内容。

爬蟲執行個體——爬取豆瓣網 top250 電影的資訊

知道了對應的 html 内容之後,接下來就是解析 html,擷取我們想要的内容。下面我們就逐漸介紹爬取的過程:

1.擷取 html

爬蟲執行個體——爬取豆瓣網 top250 電影的資訊

如上圖所示,由于每頁隻展示 25 個電影的資訊,要想擷取所有電影的資訊,需要通過一個循環來擷取全部 10 頁的内容。

1.1 導入所需的第三方庫

import requests
from bs4 import BeautifulSoup
import time
import      

1.2 發送請求

1.2.1 設定 headers

由于豆瓣網會有反扒的機制,是以在請求網頁的時候,需要設定headers。headers 的内容如下:

headers = {
    'User-Agent': ******,
    'Cookie': ******
}      

在實際運作時,需要将 ** 改成真實的 User-Agent 和 Cookie。

1.2.2 生成 url

第一頁的 url 為:​

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

​​。第二頁的 url 為:​

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

​​。第三頁的 url 為:​

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

​。從上面三個 url 的組成可以看出,隻有 start 後面的數字在變,其他的都不變。我們可以根據這個規律來擷取所有的 url。

1.2.3 發送請求擷取響應

for i in range(10):
    response = requests.get(
        'https://movie.douban.com/top250?'+'start='+str(25*i)+'&filter=', headers=headers)      

2.解析 html

2.1 響應解析

.text, 'lxml')
    ol = soup.ol
    all_li = ol.find_all('li')
    for li in all_li:
        rank = li.find('em', class_="").string
        title = li.find('span', class_="title").string
        rating = li.find('span', class_="rating_num").string
        info = li.find('div', class_="bd").p.get_text().strip()
        country = info.split('/')[-2]
        genre = info.split('/')[-1]
        release_time = info.split('\n')[1].split('/')[0].replace(" ", "")
        director_actor = li.find('div', class_="bd").p.next_element.replace(
            "\n", "").replace(" ", "")

        ranks.append(rank)
        titles.append(title)
        ratings.append(rating)
        countrys.append(country)
        genres.append(genre)
        release_times.append(release_time)
        director_actors.append(director_actor)      

由上面的 html 内容可以看到,每部電影的資訊處于​

​<li></li>​

​​标簽内,而所有的​

​<li></li>​

​​标簽又位于​

​<ol></ol>​

​标簽内。于是,首先擷取 ol 标簽的内容,然後再擷取所有的 li 标簽的内容。擷取到所有的 li 标簽之後,對每個 li 标簽進行周遊,擷取我們想要的内容。在所有的内容擷取完成後,将内容加入到相應的存儲清單中。

3.存儲内容

在擷取我們想要的内容之後,将内容存儲到 csv 檔案。代碼如下:

with open('top250.csv', 'w') as file:
    writer = csv.writer(file, delimiter=',')

    writer.writerow(["排名", "名稱", "評分", "國家", "類型", "上映時間", "導演&主演"])

    for i in range(250):
        writer.writerow([
            ranks[i],
            titles[i],
            ratings[i],
            countrys[i],
            genres[i],
            release_times[i],
            director_actors[i]
        ])      

4.完整代碼

綜合上面每一步的代碼之後,便可以得到完整的代碼:

import requests
from bs4 import BeautifulSoup
import time
import csv

headers = {
    'User-Agent': ******,
    'Cookie': ******
}

ranks = []
titles = []
ratings = []
inqs = []
countrys = []
genres = []
release_times = []
director_actors = []

for i in range(10):
    response = requests.get(
        'https://movie.douban.com/top250?'+'start='+str(25*i)+'&filter=', headers=headers)

    soup = BeautifulSoup(response.text, 'lxml')
    ol = soup.ol
    all_li = ol.find_all('li')
    for li in all_li:
        rank = li.find('em', class_="").string
        title = li.find('span', class_="title").string
        rating = li.find('span', class_="rating_num").string
        info = li.find('div', class_="bd").p.get_text().strip()
        country = info.split('/')[-2]
        genre = info.split('/')[-1]
        release_time = info.split('\n')[1].split('/')[0].replace(" ", "")
        director_actor = li.find('div', class_="bd").p.next_element.replace(
            "\n", "").replace(" ", "")

        ranks.append(rank)
        titles.append(title)
        ratings.append(rating)
        countrys.append(country)
        genres.append(genre)
        release_times.append(release_time)
        director_actors.append(director_actor)

    time.sleep(3)


with open('top250.csv', 'w') as file:
    writer = csv.writer(file, delimiter=',')

    writer.writerow(["排名", "名稱", "評分", "國家", "類型", "上映時間", "導演&主演"])

    for i in range(250):
        writer.writerow([
            ranks[i],
            titles[i],
            ratings[i],
            countrys[i],
            genres[i],
            release_times[i],
            director_actors[i]
        ])      

5.結果