天天看點

【Easy Python】第三話:爬蟲初探——玩轉豆瓣二百五(上)前言擷取電影清單網頁資料解析提取電影URL小結

前言

一直以來,爬蟲都是許多同學學Python的目的之一,就連我敬愛的上司,也經常不恥下問一些爬蟲方面的問題。是以,我們開始實戰——以豆瓣Top 250為例,試水一下基礎的爬蟲。

“玩轉豆瓣二百五”系列分為上下兩部,所有代碼,可以在我的Github裡Douban_250找到~

工欲善其事,必先利其器。以下浏覽器操作,都基于最新版Chrome~

擷取電影清單網頁資料

爬蟲爬蟲,實質還是抓取網絡資料= =爬蟲不得急,可要一步步來——首先,我們希望獲得每一個電影的連結,把它們存起來,留着後續爬取具體内容備用。

打開豆瓣Top 250首頁,會看到電影清單的頁面,往下翻,會看到總共有10頁,每頁25個電影。打開第二頁,可以看到浏覽器的位址變成了

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

,咱們觀察一下連結——連結有一部分,

start=25

,是不是很突兀?按這樣推算,第三頁應該是

start=50

,第一頁就是

start=0

嘛= =試了一下,果真是的= =

是以,爬取250個電影連結,不難規劃——

  • 打開10個電影清單頁面——

    https://movie.douban.com/top250?start=$movie_num&filter=

    ,其中

    $movie_num

    25 * (頁數 - 1)

  • 擷取10個頁面的網頁内容——我們都知道點選電影名就能進到電影連結裡,那麼電影連結在網頁内容的機率就很大
  • 解析網頁内容,提取連結資訊

是以,每一頁的連結,可以如下表示:

def get_start_url(page):
    # page = 0 相當于第一頁
    start_num = 25 * page
    return 'https://movie.douban.com/top250?start=%d&filter=' % start_num
           

然後,我們需要擷取這些每一頁的網頁資訊了——要擷取資訊,就涉及到交流,要交流,就要有共同的語言,約定俗成的資料格式——我們可稱之為協定(Protocol)。擷取網頁資訊,我們就常用超文本傳輸協定(HTTP),如果需要進一步保證傳輸資料的安全性,就采用超文本傳輸安全協定(HTTPS),是HTTP的擴充。豆瓣的連結以https開頭,可見是采用了HTTPS作為資料傳輸的協定。

對于一個網站來說,每一個網頁,都隻是一種資源(Resource)。資源的連結,不論是所謂的網頁,還是什麼種子下載下傳位址,都歸屬于一個概念——統一資源定位符(URL)。通常來講,如果伺服器允許的話,我們采用HTTP或者HTTPS的資料格式,采用協定約定的GET請求方式(Request Method)通路一個URL,就可以擷取該URL下相應的資源。相應地,對豆瓣二百五每一頁的URL發出GET請求,就應當可以擷取到網頁的内容。

是以首先,我們去給上述所有電影清單頁面發請求,擷取所有網頁資料。在python3裡,我們可以通過requests庫發送http/https請求,獲得請求的響應(Response)資料,提取網頁資訊。

import requests
for i in range(10):
	url = get_start_url(i)  # 就用上面說的get_start_url函數
	response = requests.get(url)
	# HTTP/HTTPS協定裡,response資料的不同狀态碼(status code)有不同含義
	# 一般2字頭表示整個請求&響應資料過程成功進行,200最常見
	# 4字頭表示請求有問題,無法獲得想要的資料,也有可能是你被伺服器小黑屋了
	# 5字頭表示伺服器背鍋,處理你的請求過程中bug了,或者是根本沒法處理請求
	if response.status_code == 200:
		html = response.text  # 提取相應的文本資訊,在此為網頁資料
		解析(html)
		存儲資料()
	else:
		print('Error at page %d with status %d!' %
			  (i + 1, response.status_code))
           

解析提取電影URL

獲得了電影清單網頁資料之後,我們需要通過某種規則,擷取網頁裡邊的電影連結。網頁資料文本一般遵從HTML(超文本标記語言)格式,我們可以通過右鍵網頁檢視源代碼看到,每一個網頁的元素(Element),都被标簽(Tag)包裹着,形式類似于這樣——

<tag1><tag2>...</tag2>...</tag1>

,标簽層層相扣,而最外層有一個

<html>

标簽包裹着所有的内容,是以整一個網頁資料類似于由标簽、元素組成,以

<html>

标簽為根的樹狀結構。在Python中,有許多第三方庫(需要額外安裝~)可以滿足解析HTML的需求,這裡以

bs4

BeautifulSoup

解析庫以及

lxml

解析引擎為例,嘗試提取豆瓣電影的連結。

from bs4 import BeautifulSoup
html = response.text  # 接上
html_parser = 'lxml'  # 指定解析引擎為lxml
soup = BeautifulSoup(html, html_parser)  # 基于網頁資料建構一個解析器
           

接下來,随便在哪一個電影清單頁面打開Chrome開發者工具,選擇Elements一欄,點選開發者工具左上角的滑鼠,再點一個電影标題,就可以

在開發者工具中定位到該标題所在的元素。

是以,看到有個标簽,

<a href="啥啥啥" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >...</a>

了嗎?點選那個href裡的内容,是不是進到了每部電影的頁面?試試看吧~

要定位這個

<a href="啥啥啥" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >...</a>

元素的位置,我們可以在開發者工具的Elements界面中右鍵點選标簽頭部,也就是

<a href="啥啥啥" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >

這一部分,然後,選擇copy -> selector,擷取該元素CSS選擇器的代碼。選擇器(Selector),可以滿足定位一組或是一個特定HTML元素的需求。而BeautifulSoup,則對CSS選擇器(CSS Selector)有着較好的支援。

以第一頁的《肖申克的救贖》為例操作,copy出來的選擇器的代碼是——

#content > div > div.article > ol > li:nth-child(1) > div > div.info > div.hd > a

,看起來很長,那有沒有簡單的版本呢?仔細觀察,我們可以發現:标簽的屬性(比如

<a href="啥啥啥" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >

裡,

href

就是标簽的屬性)裡,

class

id

是較為常見的兩個。标簽屬性

class

一般指代一類特定的網頁元素排版樣式,而

id

則一般用于指代一個特定的元素。每一個電影連結的上層,都有一個

<div class="hd">

的标簽,為此,我們可以通過這個标簽下層的

<a>

标簽,尋找對應的電影連結,并存儲起來:

movie_url_file = open('movie_urls.txt', 'w', encoding='utf-8')
for movies in soup.find_all('div', class_='hd'):
	# movies表示網頁中每一個<div class="hd">标簽下的元素
	movie_url = movies.find('a')['href']  # 提取該元素下層<a>标簽的href屬性
	movie_url_file.write(movie_url + '\n')  # 把連結寫入檔案
movie_url_file.close()
           

通過這樣的操作,我們就可以獲得250個電影的url了。試試看吧~

小結

上半部分,初試爬蟲,我們抓到了豆瓣250個電影的連結。

下半部分,我們就在這250個電影的連結中,一探究竟吧~