爬蟲入門------從數據看奧斯卡陪跑健將到底是誰?學院派評委都熱衷於哪類電影?

前言

奧斯卡頒獎季雖已過去有些日子,《寄生蟲》奪得最佳影片,《1917》也不拉下風,全片的長鏡頭的確震撼,這都不是今天要蹭的過氣熱點。作爲一個電影死忠,當然還是想通過數據看看誰是奧斯卡男主最優陪跑員,誰又是白給先鋒,奧斯卡派評委都熱衷於哪類電影,以前總是聽說小李子一直在陪跑(不過他在16年就憑藉《荒野獵人》中的出色表現奪得最佳男主,還記得大衆網友燒香拜佛來保佑他奪冠),今天就通過爬取一些歷年數據看看是不是正如影迷們所說那個維密收割機–小李子纔是陪跑之王。

準備工作

所用到一些工具

  • requests
  • lxml
  • pymongo
  • pandas
  • xpath-helper

requests就不用多說了,憑此庫可以滿足80%的爬蟲任務了;
lxml庫主要是使用xpath進行提取網頁中的一些數據;
pymongo是爲了將提取的一些非結構化數據進行存儲,前面已有一篇介紹的文章MongoDB快速學習,有興趣的可以點擊看看一下一些基本的安裝增刪改查等等;
pandas這麼無情的庫就不用多介紹了吧,本文用它來讀取MongoDB中的數據;
xpath-helper是一個直接可以在網頁上使用xpath表達式提取信息的工具,需要自己安裝,如沒有安裝包,請私信或留言聯繫我。

目標

個人認爲選取目標首先還是選擇那些突破反爬比較容易的網站,這樣可以節省很多時間,不過也可以嘗試反爬還可以的,這樣可以鍛鍊技巧,各有利弊。本次選擇了時光網,因爲有幾個榜單就是專門提供各大獎的歷史信息,不用特意去找,信息比較集中。

確認提取鏈接

首先登錄時光網首頁,拉到最下面找到特色榜單選項,點擊進入:
在這裏插入圖片描述
然後搜索"奧斯卡":
在這裏插入圖片描述
進入搜索結果頁面:
在這裏插入圖片描述
上圖用箭頭標註的即想要的結果,點擊奧斯卡歷屆最佳男主演,進入頁面:
在這裏插入圖片描述
按照慣例,按F12打開開發者選項,刷新頁面,查看請求,一般數據要麼在html頁面,要麼通過json格式,如果請求列表中數據較多,你可以點擊XHR來查看json請求,但是你會發現此選項下面並沒有請求,這時就選Doc來查看html請求:
在這裏插入圖片描述
在這裏插入圖片描述
doc下面剛好只有一個請求,直接點進去:
在這裏插入圖片描述
標紅的爲後面要用的請求url,請求方法是get,get,get重要的東西說三遍~~,這些要記住,然後切換到Response頁面,Ctrl+F搜索一個頁面上看到的詞隨便一個就行,以此來確認你找到的這個請求鏈接是正確的,我這裏搜的是華金·菲尼克斯
在這裏插入圖片描述
可以看到是有結果的,這說明我們的鏈接沒問題,接下來就開始提取想要的內容了。

提取信息

將頁面切到Element,這裏是網頁的源代碼,我們所需的信息均可以從這裏提取,打開xpath-helper,頁面介紹如下:
在這裏插入圖片描述
這裏就暫時不介紹xpath語法了,直接進行查詢使用了,以後會考慮專門出一篇xpath語法博客。
點擊箭頭選擇想要的元素,如最佳男演員獲獎者:
在這裏插入圖片描述
在這裏插入圖片描述
所以獲獎者的外層元素爲(div class=‘event_awards event_list’)—>(dl)–>(div class=‘yellowbox’)–>(div class=‘review_list’)–>(dl class=‘fix’)---->(dd)–>(strong class='px14 c_a5)–>a,可以編寫xpath語句進行測試:
在這裏插入圖片描述
在這裏插入圖片描述
年份可以一次提取到,最後在代碼裏對應一下即可。
在這裏插入圖片描述
由上所示每一年都在dd標籤中,代碼中循環讀取即能讀到所有年份的數據,這裏再提一下提名者是在div class='bluebox'下,提取方法與前一個yellowbox一樣。

代碼

這裏使用Python類進行提取,只介紹主要的部分了:

導入庫

import requests
import random
import json
import re
import time
from lxml import etree
from ua import USER_AGENT   #請求頭集合
from spider.dbs import StoreData  #自己寫的一個打開mongdb數據庫的類

StoreData

class StoreData():
	def __init__(self, host="127.0.0.1", db="douban", port=27017):
		self.host = host
		self.port = port
		self.client = self.connect(host, port)
		
	def connect(self, host, port):
		return MongoClient(host, port)

初始化

class Mtime():
	def __init__(self):
		self.osc_first_url= "http://award.mtime.com/3/award/31/" #第一頁鏈接
		self.osc_url = "http://award.mtime.com/3/award/31/index-{}.html"##第二頁開始鏈接
		self.db = StoreData().client["movie"]  #mongodb
		self.session =requests.Session()  # 創建session對象,保持cookies
	

鏈接在前面已經說過了,有一點忘記提了,第一頁鏈接和第二頁鏈接不太一樣,不能用通用的鏈接方式,具體看上面代碼裏。

下載函數

注意一定要用user-agent,這是基本反反爬。

	def download_page(self,url,**headers_kwargs):
		user_agent = random.choice(USER_AGENT)
		headers = {
			"User-Agent": user_agent,
				}
		if headers_kwargs:
			headers.update(headers_kwargs)
		#get方法,前面截圖裏面已經註釋過
		resp = self.session.get(url, headers=headers)		
		return resp

解析函數

下面直接上提取解析代碼,不太懂的看一下注釋。

	def parser(self,text):
		#將html文本轉爲etree類型,爲了使用xpath
		xp_html = etree.HTML(text)
		##年份提取  
		year = xp_html.xpath("//div[@class='event_awards event_list']/dl/dt/text()")  
		## 所需的信息都在這裏面,只需要在後面循環讀取
		all_movie= xp_html.xpath("//div[@class='event_awards event_list']/dl/dd")
		for y,movie in zip(year,all_movie):
			try:
			## 獲獎影片解析規則
			#這裏是爲了防止空,與scrapy的extract_fistrt()一樣
				_winning_movie = movie.xpath("div[@class='yellowbox']//strong[@class='px14 c_a5']/a/text()")
				
				winning_movie = _winning_movie[0].split()[0] if _winning_movie else ""
				
				## 獲獎人的鏈接
				_href = movie.xpath("div[@class='yellowbox']//strong[@class='px14 c_a5']/a/@href")
				href = _href[0] if _href else ""
				
				## 提名人員
				_nominated_movie = movie.xpath("div[@class='bluebox']//strong[@class='px14c_a5']//a/text()")
				nominated_movie = _nominated_movie if _nominated_movie else ""
				nominated_movie = [nm.split()[0] for nm in nominated_movie]
				
				## 提名人員鏈接
				_nominated_href = movie.xpath("div[@class='bluebox']//strong[@class='px14c_a5']//a/@href")
				nominated_href = _nominated_href if _nominated_href else ""

				# 提取四位年份,這裏是因爲解析結果是類似於2020年(第92屆)這樣的,所以要稍微處理一下

				_yy = re.findall("\d{4}",y)
				yy = _yy[0] if _yy else  ""
				## 提取屆次
				_sessions = re.findall("第(\d{2,3})屆",y)
				sessions = _sessions[0] if _sessions else ""
				
				
				award_info = {
					"年份":yy,
					"屆次":sessions,
					"獲獎":winning_movie,
					"獲獎影片鏈接":href,
					"提名":nominated_movie,
				}
				#award_info .update(inner_context)
				print(award_info)
				#存儲到mongdb中
				#actor爲我MongoDB movie數據庫裏的一個集合名
				ret = self.db["actor"].insert(award_info)
				print(ret)
			except Exception as e:
				print(e)

主函數

	def main(self):
		for i in range(1,10):
		#判斷是否是第一頁,以此控制url
			if i == 1:
				url = self.osc_first_url
			else:
				url = self.osc_top100.format(i)
			resp =self.download_page(url)
			#解決中文亂碼
			resp.encoding = "utf-8"
			self.parser(resp.text)
			#一共就10頁,慢慢爬無所謂,不要影響人家的性能
			rd = random.randint(5,15)
			print("睡眠{}秒".format(rd))
			time.sleep(rd)

爬取結果

在這裏插入圖片描述
在這裏插入圖片描述
這是MongoDB的展示結果,順便一提這個MongoDB可視化軟件還不錯,有需要的可以私信、留言,老外的產品,不是打廣告哦。

小結

至此就爬取完了最佳男演員的數據,因爲這幾個榜單前端模板都一樣,最佳影片也是同理,修改一下url鏈接即可。

數據可視化

讀取數據

只需從MongoDB中讀取數據,這裏使用的是pandas庫,下面是鏈接數據庫和讀取過程:

import  pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from spider.dbs import StoreData
import collections
#如果要顯示中文則需要設置字體
font = FontProperties(fname='C:\Windows\Fonts\simhei.ttf', size=10)
client = StoreData().client
mv = client["movie"]
act = mv["actor"]
oscar = mv["oscar"]

data = pd.DataFrame(list(act.find()))
osc = pd.DataFrame(list(oscar.find()))

matplotlib如果要顯示中文則需要設置字體,參考上面,本文可視化相對簡單,就只貼獲獎次數前20的代碼了:

#統計獲獎次數
data["獲獎"].value_counts()[:20].plot.bar()
#設置X軸樣式
plt.xticks(color='blue',rotation=90,fontproperties=font)
plt.title("獲獎次數前20",fontproperties=font)
plt.show()

獲獎次數前20

在這裏插入圖片描述
這裏有點納悶了,印象中丹尼爾·戴-劉易斯明明獲獎獲了3次,這裏只顯示了兩次,經過我一番查看,發現時光上的丟失了2008-2010的數據(大家多包涵,懶得補充了,就用現在的數據了,大家就當做沒看見,手動狗頭保命)。

提名次數前40名

在這裏插入圖片描述
納尼,小李子的提名居然才4次,高居榜首的是拍過《阿拉伯的勞倫斯》和《特洛伊》的彼得奧圖和拍過《呼嘯山莊》和《傲慢與偏見》的勞倫斯·奧利弗。

曾提名並獲過獎的演員

在這裏插入圖片描述
這次通過時間魔法把小李子強行排到第一位,哈哈。

陪跑運動員(一直陪跑,一直爽)

在這裏插入圖片描述
心疼彼得奧圖。

評委喜歡的

在這裏插入圖片描述
可以看到奧斯卡這些學院派評委還是相對喜歡劇情愛情喜劇人物傳記犯罪歷史戰爭兩兩組合或三三組合的電影,怪不得《盜夢空間》和《蝙蝠俠》沒獲獎。

結束

本文簡要的介紹瞭如何通過網頁獲取數據並進行一些數據可視化展示。
更多內容請關注從今天開始種樹
關注知識圖譜與大數據公衆號,獲取更多內容。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章