選題的背景
為什么要選擇此選題?要達到的數據分析的預期目標是什么?
隨着經濟社會的快速發展,電影作為精神文化產品,得到越來越多人的青睞,人們對電影的評價頁也參差不齊,在海量的資源中如何盡快找到符合個人品味的電影,成為觀眾新的問題。基於Python的數據爬蟲技術是目前使用最廣泛的方法之一,它能夠以最快捷的方式展示用戶體驗數據,幫助觀眾進行影片選擇。豆瓣電影是著名的電影網站,通過豆瓣電影提供的開放接口大規模地獲取電影相關數據。
主題式網絡爬蟲設計方案
1.主題式網絡爬蟲名稱 豆瓣電影top250
2.主題式網絡爬蟲爬取的內容與數據特征分析
用Python編寫爬蟲程序抓取了Top250排行榜的影片榜單信息,爬取電影的短評、評分、評價數量等數據,並結合Pythorn的多個庫(Pandas、Numpy、Matplotib),使用Numpy系統存情和處理大型數據,最終通過圖表展示出來。網絡信息資源充盈的今天,網絡信息的獲取工作十分重要,該設計的意義在於為用戶觀影提供決策支持。
3.主題式網絡爬蟲設計方案概述
本次設計通過request庫訪問,用BeautifulSoup分析網頁結構獲取數據,將采集到的數據保存在本地
Htmls 頁面解析
網絡爬蟲程序設計
1.數據爬取與采集
1 import time 2 import requests 3 import re 4 from openpyxl import workbook # 寫入Excel表所用 5 from bs4 import BeautifulSoup as bs 6 from matplotlib import pyplot as plt 7 import matplotlib 8 import seaborn as sns 9 from scipy.optimize import leastsq 10 import numpy as np 11 import scipy as sp 12 import pandas as pd 13 14 class Top250: 15 def __init__(self): 16 #起始地址 17 self.start_url = 'https://movie.douban.com/top250' 18 #請求頭,瀏覽器模擬 19 self.headers = { 20 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36', 21 } 22 #爬取頁數 23 self.page_num = 10 24 25 26 def get_page_url(self): 27 n = 0 #第一頁開始,下標0 28 while n<self.page_num: 29 yield self.start_url+'?start={}&filter='.format(n*25) 30 n += 1 31 32 def getHtml(self): 33 gu = self.get_page_url() #url生成器 34 for url in gu: 35 html = requests.get(url,headers=self.headers).text 36 yield html 37 38 def getData(self): 39 gh = self.getHtml() # html源碼生成器 40 for html in gh: # html:網頁源碼 41 soup = bs(html, 'lxml') 42 for info in soup.find_all('div', class_='info'): 43 c_name = info.find('span',class_='title').text.strip() # 得到電影中文名 44 message = info.select('div.bd p')[0].text.strip() #得到導演、主演、年份、地區信息 45 yat = re.search('[0-9]+.*\/?', message).group().split('/') #得到年份、地區、類型信息列表 46 year,area,type = yat[0],yat[1],yat[2]#得到年份、地區、類型 47 da = re.search('導演.+\s',message).group().strip()+'...' #得到導演、主演混合信息 48 director = re.findall('導演:(.+?)\s',da)[0].strip() #得到導演信息 49 #得到主演信息,不存在時發生異常,進行異常處理 50 try: 51 mainActors = re.findall('主演:(.+?)[.,]+',da)[0].strip() 52 except IndexError: 53 mainActors = '暫無主演信息' 54 mark_info = info.find('div',class_='star') #得到評分、評價人數混合信息 55 score= mark_info.find('span',class_='rating_num').text.strip()#得到評分 56 count = re.search('[0-9]+',mark_info.select('span')[3].text).group() #得到評價人數 57 #得到簡介,捕捉不存在時的異常 58 try: 59 quote = info.select('p.quote span')[0].text.strip() 60 except IndexError: 61 quote = '該影片暫時無簡介' 62 yield [c_name,year,area,type,director,mainActors,score,count,quote] 63 64 65 def saveToExcel(self,file_name): 66 wb = workbook.Workbook() # 創建Excel對象 67 ws = wb.active # 獲取當前正在操作的表對象 68 ws.append(['電影名', '年份', '地區', '劇情類型', '導演', '主演', '評分', '評論人數', '簡介']) 69 gd = self.getData() #數據生成器 70 for data in gd: 71 ws.append(data) 72 wb.save(file_name) 73 74 if __name__ == '__main__': 75 start = time.time() 76 top = Top250() 77 try: 78 top.saveToExcel('top250.xlsx') 79 print('抓取成功,用時%4.2f'%(time.time()-start)+'秒') 80 except Exception as e: 81 print('抓取失敗,原因:%s'%e)
2.對數據進行清洗和處理
1 df = pd.DataFrame(pd.read_excel('top250.xlsx'),columns=['排名','電影名', '年份', '地區', '劇情類型', '導演', '主演', '評分', '評論人數', '簡介']) 2 print(df.head()) 3 # 讀取excel文件 4 5 6 print(df.head()) 7 # 刪除無效行與列 8 9 print(df.isnull().sum()) 10 # 返回0,表示沒有空值 11 print(df.isna().head()) 12 # 統計缺失值 13 print(df.isna().head()) 14 # 查找重復值
3.數據分析與可視化
1 x = df.排名 2 y = df['評分'][:250] 3 plt.xlabel('評分') 4 plt.ylabel('排名') 5 plt.bar(x,y) 6 plt.title("排名與評分比較圖") 7 plt.show() 8 #柱狀圖
1 x = df.排名 2 y = df['評分'][:250] 3 plt.xlabel('排名') 4 plt.ylabel('評分') 5 plt.plot() 6 plt.scatter(x,y) 7 plt.title("排名與評分比較圖") 8 plt.show() 9 #散點圖
1 sns.lmplot(x='排名',y='評分',data=df) 2 #線性圖
4.回歸方程
1 X=df.loc[:,'排名'] 2 Y=df.loc[:,'評分'] 3 def func(params,x): 4 a,b,c=params 5 return a*x*x+b*x+c 6 def error_func(params,x,y): 7 return func(params,x)-y 8 P0=[1,9.0] 9 def main(): 10 plt.figure(figsize=(8,6)) 11 P0=[1,9.0,1] 12 Para=leastsq(error_func,P0,args=(X,Y)) 13 a,b,c=Para[0] 14 print("a=",a, "b=",b, "c=",c) 15 plt.scatter(X,Y,color="green",label="樣本數據",linewidth=2) 16 x=np.linspace(1,250,40) 17 y=a*x*x+b*x+c 18 plt.plot(x,y,color="red",label="擬合曲線",linewidth=2) 19 plt.xlabel('排名') 20 plt.ylabel('得分') 21 plt.title("排名與得分回歸方程") 22 plt.grid() 23 plt.legend() 24 plt.show() 25 main()
5.完整代碼
1 import time 2 import requests 3 import re 4 from openpyxl import workbook # 寫入Excel表所用 5 from bs4 import BeautifulSoup as bs 6 from matplotlib import pyplot as plt 7 import matplotlib 8 import seaborn as sns 9 from scipy.optimize import leastsq 10 import numpy as np 11 import scipy as sp 12 import pandas as pd 13 14 class Top250: 15 def __init__(self): 16 #起始地址 17 self.start_url = 'https://movie.douban.com/top250' 18 #請求頭,瀏覽器模擬 19 self.headers = { 20 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36', 21 } 22 #爬取頁數 23 self.page_num = 10 24 25 26 def get_page_url(self): 27 n = 0 #第一頁開始,下標0 28 while n<self.page_num: 29 yield self.start_url+'?start={}&filter='.format(n*25) 30 n += 1 31 32 def getHtml(self): 33 gu = self.get_page_url() #url生成器 34 for url in gu: 35 html = requests.get(url,headers=self.headers).text 36 yield html 37 38 def getData(self): 39 gh = self.getHtml() # html源碼生成器 40 for html in gh: # html:網頁源碼 41 soup = bs(html, 'lxml') 42 for info in soup.find_all('div', class_='info'): 43 c_name = info.find('span',class_='title').text.strip() # 得到電影中文名 44 message = info.select('div.bd p')[0].text.strip() #得到導演、主演、年份、地區信息 45 yat = re.search('[0-9]+.*\/?', message).group().split('/') #得到年份、地區、類型信息列表 46 year,area,type = yat[0],yat[1],yat[2]#得到年份、地區、類型 47 da = re.search('導演.+\s',message).group().strip()+'...' #得到導演、主演混合信息 48 director = re.findall('導演:(.+?)\s',da)[0].strip() #得到導演信息 49 #得到主演信息,不存在時發生異常,進行異常處理 50 try: 51 mainActors = re.findall('主演:(.+?)[.,]+',da)[0].strip() 52 except IndexError: 53 mainActors = '暫無主演信息' 54 mark_info = info.find('div',class_='star') #得到評分、評價人數混合信息 55 score= mark_info.find('span',class_='rating_num').text.strip()#得到評分 56 count = re.search('[0-9]+',mark_info.select('span')[3].text).group() #得到評價人數 57 #得到簡介,捕捉不存在時的異常 58 try: 59 quote = info.select('p.quote span')[0].text.strip() 60 except IndexError: 61 quote = '該影片暫時無簡介' 62 yield [c_name,year,area,type,director,mainActors,score,count,quote] 63 64 65 def saveToExcel(self,file_name): 66 wb = workbook.Workbook() # 創建Excel對象 67 ws = wb.active # 獲取當前正在操作的表對象 68 ws.append(['電影名', '年份', '地區', '劇情類型', '導演', '主演', '評分', '評論人數', '簡介']) 69 gd = self.getData() #數據生成器 70 for data in gd: 71 ws.append(data) 72 wb.save(file_name) 73 74 if __name__ == '__main__': 75 start = time.time() 76 top = Top250() 77 try: 78 top.saveToExcel('top250.xlsx') 79 print('抓取成功,用時%4.2f'%(time.time()-start)+'秒') 80 except Exception as e: 81 print('抓取失敗,原因:%s'%e) 82 83 df = pd.DataFrame(pd.read_excel('top250.xlsx'),columns=['排名','電影名', '年份', '地區', '劇情類型', '導演', '主演', '評分', '評論人數', '簡介']) 84 print(df.head()) 85 # 讀取excel文件 86 87 88 print(df.head()) 89 # 刪除無效行與列 90 91 print(df.isnull().sum()) 92 # 返回0,表示沒有空值 93 print(df.isna().head()) 94 # 統計缺失值 95 print(df.isna().head()) 96 # 查找重復值 97 98 from matplotlib import pyplot as plt 99 import matplotlib 100 import seaborn as sns 101 from scipy.optimize import leastsq 102 103 import numpy as np 104 import scipy as sp 105 import pandas as pd 106 107 x = df.排名 108 y = df['評分'][:250] 109 plt.xlabel('評分') 110 plt.ylabel('排名') 111 plt.bar(x,y) 112 plt.title("排名與評分比較圖") 113 plt.show() 114 #柱狀圖 115 116 117 x = df.排名 118 y = df['評分'][:250] 119 plt.xlabel('排名') 120 plt.ylabel('評分') 121 plt.plot() 122 plt.scatter(x,y) 123 plt.title("排名與評分比較圖") 124 plt.show() 125 #散點圖 126 127 sns.lmplot(x='排名',y='評分',data=df) 128 #線性圖 129 130 X=df.loc[:,'排名'] 131 Y=df.loc[:,'評分'] 132 def func(params,x): 133 a,b,c=params 134 return a*x*x+b*x+c 135 def error_func(params,x,y): 136 return func(params,x)-y 137 P0=[1,9.0] 138 def main(): 139 plt.figure(figsize=(8,6)) 140 P0=[1,9.0,1] 141 Para=leastsq(error_func,P0,args=(X,Y)) 142 a,b,c=Para[0] 143 print("a=",a, "b=",b, "c=",c) 144 plt.scatter(X,Y,color="green",label="樣本數據",linewidth=2) 145 x=np.linspace(1,250,40) 146 y=a*x*x+b*x+c 147 plt.plot(x,y,color="red",label="擬合曲線",linewidth=2) 148 plt.xlabel('排名') 149 plt.ylabel('得分') 150 plt.title("排名與得分回歸方程") 151 plt.grid() 152 plt.legend() 153 plt.show() 154 main()
經過對主題數據的分析與可視化可以讓數據以更生動形象具體的方式呈現在我們眼前
在完成此設計過程中發現通過Chrome瀏覽器對於寫爬蟲非常有用,Chrome自帶的開發者工具能幫助分析網頁的源碼、資源和數據包。特別是要寫表單提交一類功能時,Chrome自帶的抓包功能非常好用,通過分析包結構可以實現各類復雜表單的模擬提交。