零基礎Python爬蟲實戰:豆瓣電影TOP250

2021-01-04 百家號

我們曾經抓取過貓眼電影TOP100,並進行了簡單的分析。但是眾所周知,豆瓣的用戶比較小眾、比較獨特,那麼豆瓣的TOP250又會是哪些電影呢?

我在整理代碼的時候突然發現一年多以前的爬蟲代碼竟然還能使用……那今天就用它來演示下,如何通過urllib+BeautifulSoup來快速抓取解析豆瓣電影TOP250。

一、觀察網頁地址

首先我們觀察url地址,連續點擊幾頁之後我們發現,豆瓣電影TOP250一共分10頁,每頁有25部電影,每頁的url地址的格式為https://movie.douban.com/top250?start={0}&filter=,大括號中的部分用這一頁的第一部電影的編號代替,編號從0開始一直到249。

因此我們可以通過格式化字符串來生成所有的url地址:

url_init = ' urls = [url_init.format(x * 25) for x in range(10)]print(urls)輸出為:

['https://movie.douban.com/top250?start=0&filter=', 'https://movie.douban.com/top250?start=25&filter=', 'https://movie.douban.com/top250?start=50&filter=', 'https://movie.douban.com/top250?start=75&filter=', 'https://movie.douban.com/top250?start=100&filter=', 'https://movie.douban.com/top250?start=125&filter=', 'https://movie.douban.com/top250?start=150&filter=', 'https://movie.douban.com/top250?start=175&filter=', 'https://movie.douban.com/top250?start=200&filter=', 'https://movie.douban.com/top250?start=225&filter=']當然,這個地址未必就是我們需要請求的地址。我們先打開TOP250的第一頁,右鍵檢查,單擊進入網絡(Network)選項卡,刷新一下,可以看到出現了一大堆請求的返回結果,我們先打開第一個document類型的請求。

我們切換到Headers標籤,可以看到,在General下,Request URL的取值與網頁地址一樣。也就是說,我們上邊生成的10條url,正是我們需要請求的地址。

二、定位信息位置

接下來我們看一下電影的信息藏在哪裡。我們切換到Response標籤下,搜索網頁中的內容,比如我們先搜一下榜首的名稱:肖申克的救贖。

可以看到,所有的電影信息都在一個class="grid_view"的<ol>(有序列表)標籤下,每一部電影是一個<li>標籤。

在每個<li>下:

標題藏在一個class="title"的<span>標籤下;導演、主演、上映年份、地區、類型藏在一個<div>的子標籤<p>中;得分和評分人數在<div>下

好,接下來我們就開始抓取並解析這些內容。

三、抓取並解析

首先我們定義一個函數,用來打開url並返回BeautifulSoup對象。

# -*- coding:utf-8 -*-from urllib.request import urlopenfrom bs4 import BeautifulSoupfrom collections import defaultdictimport pandas as pdimport timeimport reclass DoubanMovieTop(): def __init__(self): self.top_urls = ['https://movie.douban.com/top250?start={0}&filter='.format(x*25) for x in range(10)] self.data = defaultdict(list) self.columns = ['title', 'link', 'score', 'score_cnt', 'top_no', 'director', 'writers', 'actors', 'types', 'edit_location', 'language', 'dates', 'play_location', 'length', 'rating_per', 'betters', 'had_seen', 'want_see', 'tags', 'short_review', 'review', 'ask', 'discussion'] self.df = None def get_bsobj(self, url): html = urlopen(url).read().decode('utf-8') bsobj = BeautifulSoup(html, 'lxml') return bsobj在這個函數中,我們使用urllib.requests.urlopen來發起請求,對返回的響應結果,我們使用.read()方法來讀取內容。但是這裡讀取到的內容是字節(bytes),我們要將其轉化為字符串,所以我們要再使用字節對象的.decode('utf-8')方法進行轉化;然後我們使用bs4.BeautifulSoup()從字符串中生成BeautifulSoup對象。

這裡我們為什麼選擇utf-8編碼進行解碼呢?這是因為這個網頁的編碼正是utf-8。一般情況下,我們可以從網頁的<head>中找到編碼信息,這樣我們就可以對於不同編碼的網頁進行針對性的解碼了。

接下來我們開始解析電影的信息。我們定義一個函數,以上邊get_bsobj(url)函數輸出的BeautifulSoup對象為輸入,以數據列表為輸出。

def get_info(self): for url in self.top_urls: bsobj = self.get_bsobj(url) main = bsobj.find('ol', {'class': 'grid_view'}) # 標題及連結信息 title_objs = main.findAll('div', {'class': 'hd'}) titles = [i.find('span').text for i in title_objs] links = [i.find('a')['href'] for i in title_objs] # 評分信息 score_objs = main.findAll('div', {'class': 'star'}) scores = [i.find('span', {'class': 'rating_num'}).text for i in score_objs] score_cnts = [i.findAll('span')[-1].text for i in score_objs] for title, link, score, score_cnt in zip(titles, links, scores, score_cnts): self.data[title].extend([title, link, score, score_cnt]) bsobj_more = self.get_bsobj(link) more_data = self.get_more_info(bsobj_more) self.data[title].extend(more_data) print(self.data[title]) print(len(self.data)) time.sleep(1)我們在榜單列表頁面直接獲取了標題、電影詳情頁面地址、評分、評分人數信息。

接下來,可以看到我對所有的電影詳情頁面進行了一個循環抓取解析,這是因為在榜單頁面中信息展示不全,且這裡的信息不夠豐富,在詳情頁中,我們可以獲取非常豐富的數據,包括導演、編劇、演員、上映時間和地區、語言、別名、短評數、影評數、多少人想看、多少人看過……

獲得了這麼多信息之後,我們可以進行更加深入的分析,因此我們選擇進入詳情頁進一步抓取更多信息。因此我們需要定義一個函數,用來解析詳情頁。

豆瓣的頁面抓取難度較小,不過我們這裡定義了較多的欄位,因此這個函數會顯得比較長。這個函數裡我們使用了兩個try...except...來應對異常,這是因為有些電影沒有編劇或者主演,這會導致抓取異常,針對這種情況,我們直接將該欄位留空即可。

每個欄位抓取的表達式都是根據返回的源碼得到的,BeautifulSoup的使用非常簡單,幾分鐘就可以上手,半小時就可以入門。事實上我現在更喜歡使用XPath表達式,更靈活、更強大,對XPath的使用不了解的同學可以去看我的另一篇抓取網易雲音樂的文章。在這個例子中,有些BeautifulSoup不太容易實現的部分,我們結合了re正則表達式來完成。

關於BeautifulSoup的使用,可以參考這份教程:https://docs.pythontab.com/beautifulsoup4/。至於學習程度,仍然是按照我們的二八法則,不需深究,學習最少的內容,覆蓋最多的應用即可,剩下的在實戰中遇到了再去檢索學習即可。

def get_more_info(self, bsobj): # 榜單排名 top_no = bsobj.find('span', {'class': 'top250-no'}).text.split('.')[1] # 更多信息 main = bsobj.find('div', {'id': 'info'}) # 導演 dire_obj = main.findAll('a', {'rel': 'v:directedBy'}) director = [i.text for i in dire_obj] # 編劇 try: writer_obj = main.findAll('span', {'class': 'attrs'})[1] writers = [i.text for i in writer_obj.findAll('a')] except Exception as e: writers = [] print(e) # 主演 try: actor_obj = main.findAll('a', {'rel': 'v:starring'}) actors = [i.text for i in actor_obj] except Exception as e: actors = [] print(e) # 類型 type_obj = main.findAll('span', {'property': 'v:genre'}) types = [i.text for i in type_obj] # 製片地區 pattern = re.compile('地區: (.*?)\n語言', re.S) edit_location = re.findall(pattern, main.text)[0] # 語言 pattern2 = re.compile('語言: (.*?)\n上映日期') language = re.findall(pattern2, main.text)[0] # 上映日期/地區 date_obj = main.findAll('span', {'property': 'v:initialReleaseDate'}) dates = [i.text.split('(')[0][:4] for i in date_obj] play_location = [i.text.split('(')[1][:-1] for i in date_obj] # 片長 length = main.find('span', {'property': 'v:runtime'})['content'] # 5星到1星比例 rating_obj = bsobj.findAll('span', {'class': 'rating_per'}) rating_per = [i.text for i in rating_obj] # 好於 better_obj = bsobj.find('div', {'class': 'rating_betterthan'}) betters = [i.text for i in better_obj.findAll('a')] # 想看/看過 watch_obj = bsobj.find('div', {'class': 'subject-others-interests-ft'}) had_seen = watch_obj.find('a').text[:-3] want_see = watch_obj.findAll('a')[-1].text[:-3] # 標籤 tag_obj = bsobj.find('div', {'class': 'tags-body'}).findAll('a') tags = [i.text for i in tag_obj] # 短評 short_obj = bsobj.find('div', {'id': 'comments-section'}) short_review = short_obj.find('div').find('span', {'class': 'pl'}).find('a').text.split(' ')[1] # 影評 review = bsobj.find('a', {'href': 'reviews'}).text.split(' ')[1] # 問題 ask_obj = bsobj.find('div', {'id': 'askmatrix'}) ask = ask_obj.find('h2').find('a').text.strip()[2:-1] # 討論 discuss_obj = bsobj.find('p', {'class': 'pl', 'align': 'right'}).find('a') discussion = discuss_obj.text.strip().split('(')[1][2:-2] more_data = [top_no, director, writers, actors, types, edit_location, language, dates, play_location, length, rating_per, betters, had_seen, want_see, tags, short_review, review, ask, discussion] return more_data成功抓取之後,我們還需要定義一個函數,用來將數據緩存到本地或其他途徑(比如資料庫),用於後續分析。

def dump_data(self): data = [] for title, value in self.data.items(): data.append(value) self.df = pd.DataFrame(data, columns=self.columns) self.df.to_csv('douban_top250.csv', index=False)好了,一個針對豆瓣電影TOP250的爬蟲就寫完了,接下來我們執行抓取。

if __name__ == '__main__': douban = DoubanMovieTop() douban.get_info() douban.dump_data()抓取完成後,我們就可以看到我們的數據了。

那麼有人可能會問,我們抓取到數據就結束了嗎?

當然沒有,在下一篇文章中,我們會實戰演練如何對我們得到的數據進行數據清洗和分析挖掘。

相關焦點

  • Python 爬蟲實戰入門(上)
    官網可以進行下載https://www.python.org/downloads/release/python-365/安裝的時候注意選中把python3.6添加到path,然後點擊Customize installation
  • 誰說Java不能搞爬蟲的?今天帶你一起爬取豆瓣電影Top250
    的教程,也是從最基礎的網頁爬蟲開始,給大家講講網頁爬蟲的小技巧。我想寫個爬蟲是不是還得先學會python?程式設計師的頭髮不知道多寶貴嗎?花那麼多時間學習語言,是想造孽啊?先打開我要爬取數據的網頁:豆瓣電影Top250我們先來分析一下這個網頁
  • 某大佬直接用Python爬取豆瓣top250,簡單粗暴
    首先需要安裝好爬蟲需要用到的python庫 開發工具使用的是pycharm1:request 網絡請求模塊2:lxml 取數據的模塊 這裡用的是xpath 沒有用bs43.xlwings 對Excel進行讀寫的模塊如果安裝失敗 或者安裝緩慢 可以參考之前的博客 將pycharm鏡像更換為清華大學鏡像一鍵直達 更換鏡像
  • 大佬用Python爬取豆瓣電影——Top250,驚呆啦
    前言:網際網路行業在迅速發展,尤其是程式語言「Python」,在各大行業都居於重要位置,有了它人們的辦公效率大大提高,下面看看它的威力有多大用Python爬取豆瓣電影——top250,連最近最火的《我和我的家鄉
  • 豆瓣電影頁面爬蟲2020版
    豆瓣電影反爬蟲機制升級了,網上的Python爬蟲教程基本上都不能用了。以前直接requests.get()就能獲取的頁面現在是<Response [418]>錯誤。2020年正確的豆瓣電影爬蟲姿勢是怎樣的?Request請求要帶HeadersHeaders是什麼?
  • Python 爬蟲實戰入門(下)
    上一篇(跳轉任意門)我們通過requests將豆瓣電影top250的網頁內容都爬取下來了,但是爬取的是整個網頁內容將所有的頁面都來處理一下,參考以下代碼(test5.py):根據輸出信息,可以看到top250
  • Python數據採集案例(3):豆瓣電影TOP250採集
    實現目標本案計劃實現:通過網絡請求,獲取豆瓣電影TOP250的數據,並存儲到Json文件中。案例應用技巧:GET請求(requests):headers翻頁網頁解析(BeautifulSoup)實現過程總體來說,簡單的單線程爬蟲的實現流程如下:確定數據所在的Url,以及控制翻頁的參數
  • Python爬取豆瓣電影評分Top250
    抓取第一頁的電影信息抓取信息如下:上一節已經學習過了 —>這是傳送門本節重點在如何抓取下一頁面的信息,使250個電影信息全部收集到。多頁抓取,搜集完整250部電影信息代碼寫法根據每個網頁的特點不同而不同,發現豆瓣網頁翻頁是通過/top250?start=xxx&filter= 更改xxx的值實現的,不像某些網站採用異步操作。那寫一個while循環即可。
  • python爬蟲學習筆記:XPath語法和使用示例
    python爬蟲:XPath語法和使用示例使用技巧在一般的爬蟲實戰中需求分析:(1)要爬取的內容為豆瓣圖書top250的信息,如下圖所示:(2)所爬取的網頁連結: https://book.douban.com/top250?
  • Python爬蟲快速入門,靜態網頁爬取
    因為豆瓣有反爬蟲機制,我們無法通過直接請求伺服器來爬取數據,必須在發起請求之前將自己偽裝起來。1.1 反爬蟲反爬蟲是網站限制爬蟲的一種策略。它並不是禁止爬蟲(完全禁止爬蟲幾乎不可能,也可能誤傷正常用戶),而是限制爬蟲,讓爬蟲在網站可接受的範圍內爬取數據,不至於導致網站癱瘓無法運行。常見的反爬蟲方式有判別身份和IP限制兩種,這裡我們先介紹前者,後者稍後再提及。
  • 6大Python爬蟲實戰項目(附源碼教程)
    有很多人在剛開始學習Python的時候,都特別期待能用Python寫一個爬蟲腳本,小編這裡總結幾個實戰項目,如果你想學習Python爬蟲的話,可以挑選感興趣的學習【python 網站信息爬蟲】該項目使用 Python 語言及 scrapy 開發一個網絡信息爬蟲,爬取實驗樓的課程數據,並將爬取的課程信息保存在一個
  • Python Tool 101 - Tool 002 - Python 情感分析 SnowNLP
    提出問題:SnowNLP分析豆瓣電影簡介的情感度解決方案:爬蟲選用:scrapy資料庫選用:mongodbpython環境選用:python3情感分析選用:SnowNLP實際操作:第一步安裝mongodb資料庫第二步安裝python
  • Python視頻教程網課編程零基礎入門數據分析網絡爬蟲全套Python...
    本課程為python教程大合集,包含python所有就業方向,每套課程均來自市面上主流培訓機構的原版教程,價值都在數百元以上 每套課程均包含:視頻課程+課件+原始碼 重要:建議根據自己工作方向和需求,重點選擇2到3套課程學精,吃透,然後在工作 重要:零基礎小白建議先選擇零基礎全能篇的一套課程學精
  • 最簡單的Python爬蟲,僅3步11行代碼爬取豆瓣電影排名
    提到網絡爬蟲,很多人望而卻步,覺得非常難,其實非如此,哪怕沒有爬蟲基礎,也可以寫出一個簡單的爬蟲。萬丈高樓平地起,今天分享一個最簡單的爬蟲,目的是通過案例,使大家對爬蟲有一個直觀的認識。第一步:確定目標爬蟲的第一步是要確定爬取的目標,沒有目標就沒有方向,更無從寫代碼。
  • Python爬取豆瓣電影——Top250,威力之大
    爬取豆瓣電影Top250,在家看熱門電影而且不用會員充值For循環豆瓣頁面上有25部電影,而我們需要抓取每部電影的標題、導演、年份等等信息。就是說我們要循環25次,操作每一部電影。for item in soup.find_all('div',"info"):就是這個意思。
  • Python爬蟲入門並不難,甚至進階也很簡單
    這裡給你一條平滑的、零基礎快速入門的學習路徑:1.了解爬蟲的基本原理及過程2.Requests+Xpath 實現通用爬蟲套路3.了解非結構化數據的存儲掌握之後,你會發現爬蟲的基本套路都差不多,一般的靜態網站根本不在話下,小豬、豆瓣、糗事百科、騰訊新聞等基本上都可以上手了。
  • PythonPython100個練手項目|github|瀏覽器|爬蟲|python|斷點_網易...
    天貓商品數據爬蟲    3. 爬取淘寶我已購買的寶貝數據    4. 每天不同時間段通過微信發消息提醒女友    5. 爬取5K解析度超清唯美壁紙    6. 爬取豆瓣排行榜電影數據(含GUI界面版)    7.
  • 超適合Python小白的乾貨,Python數據分析50個實戰項目
    分析幾十萬條知乎數據,我挖掘出了這些秘密4.用(大)數據全方位解讀電視劇《大秦帝國之崛起》5.以虎嗅網4W+文章的文本挖掘為例,展現數據分析的一整套流程6.從大數據輿情傳播角度看《三生三世十裡桃花》7.北京二手房房價分析8.kaggle數據分析實踐項目練習——人力資源分析9.大眾點評評論文本挖掘10.手機微博榜單數據爬蟲與分析
  • Python爬蟲技術路線?
    原標題:Python爬蟲技術路線?     對於初學者而言,Python爬蟲的技術路線應該怎麼取捨?     首先展示一下如何用python爬蟲requests庫進行爬取,requests庫是python爬蟲最基礎也必須掌握的庫。
  • 上映26年後,周星馳的《九品芝麻官》終於進入「豆瓣電影top250」
    《九品芝麻官》登上豆瓣top250,經歷了整整26年而今天要跟大家說的這部電影,也是周星馳眾多作品裡最被低估的存在。可是經過26年之後,終於在今年強勢殺入豆瓣top250榜單,它就是《九品芝麻官》。在上個世紀90年代,他的電影雖然票房成績很理想,可是在口碑上一直就不怎麼樣。而在各大獎項的評選上,周星馳更是不被業界認可。豆瓣評分開啟之後,周星馳的作品曾長時間處於尷尬位置自從電影屆開啟了豆瓣評分以來,電影的質量高低就直接跟評分掛鈎了。