一、選題背景
隨着社會的發展、人類生活方式的變化,電影給我們的是生活的體驗,是對人類生活的一種追溯。電影已經成為現代人類生活當中不可缺少的一部分。電影是人們無聊時的消遣,一部好的電影會使人陶醉其中,發泄我們的情緒,升華情感,讓人翱翔在充滿藝術與美的空間里。所以我通過爬取愛奇藝排行榜更好的了解當下人們的關注的電影
二、設計方案
1.主題式網絡爬蟲名稱:
python網絡爬蟲之愛奇藝排行榜的爬取及分析
2.主題式網絡爬蟲爬取的內容與數據特征分析:
爬取網頁電影排名,標題,熱度值。
3.方案概述:
訪問網頁得到狀態碼200,分析網頁源代碼,找出所需要的的標簽,逐個提取標簽保存到相同路徑csv文件中,讀取改文件,進行數據清洗,數據模型分析,數據可視化處理,繪制分布圖,用最小二乘法分析兩個變量間的二次擬合方程和繪制擬合曲線。
技術難點:做數據分析,即求回歸系數,因為標題是文字,無法與數字作比較,需要把標題這一列刪除才可。由於不明原因,輸出結果經常會顯示超出列表范圍。
三、主題頁面的結構特征分析
1.主題頁面的結構與特征分析:標題標簽為' div.rvi__tit1 '.熱度標簽 ' span.rvi__index__num'
url=https://www.iqiyi.com/ranks1/-1/0
2.頁面解析
首頁
通過查找網頁源代碼,瀏覽其中元素,並對其中元素進行解析
節點(標簽)查找方法與遍歷方法
網頁爬取
1 #導入庫 2 import requests 3 import pandas as pd 4 import numpy as np 5 import matplotlib.pyplot as plt 6 import matplotlib 7 import csv 8 import scipy as sp 9 import seaborn as sns 10 from sklearn.linear_model import LinearRegression 11 from bs4 import BeautifulSoup 12 from pandas import DataFrame 13 from scipy.optimize import leastsq 14 15 #填入要請求的服務器地址 16 url="https://www.iqiyi.com/ranks1/-1/0"#愛奇藝熱播榜影視榜單 17 18 #requests抓取網頁信息 19 def getHTMLText(url,timeout=30): 20 try: 21 r=requests.get(url,timeout=30) #用requests抓取網頁信息 22 r.raise_for_status() #異常捕捉 23 r.encoding=r.apparent_encoding 24 return r.text 25 except: 26 return'產生異常' 27 28 #html.parser表示用BeautifulSoup庫解析網頁 29 html=getHTMLText(url) 30 soup=BeautifulSoup(html,'html.parser') 31 32 print(soup.prettify()) 33 #按照標准縮進格式的結構輸出 34 35 r=requests.get(url) 36 #請求網絡 37 r.encoding=r.apparent_encoding 38 #統一編碼 39 html = r.text 40 soup = BeautifulSoup(html,'lxml') 41 #type(soup) 42 print(soup.prettify()) 43 #基於bs4庫HTML的格式輸出,讓頁面更友好的顯示
1 #獲取標題 2 title1=[] 3 for i in soup.find_all('div', 4 class_='rvi__tit1'): 5 title1.append(i.get_text().strip()) 6 title1
1 #獲取熱度 2 b1=[] 3 for i in soup.find_all('span', 4 class_='rvi__index__num'): 5 b1.append(i.get_text().strip()) 6 b1
1 #整合獲取內容 2 print('{:^50}'.format('愛奇藝熱播榜')) 3 print('{:^5}\t{:^40}\t{:^10}'.format('排名', '名稱', '熱度')) 4 for i in range(25): 5 print('{:^5}\t{:^40}\t{:^10}'.format(i+1, title1[i], b1[i])) 6 lit1=[] 7 for i in range(25): 8 lit1.append([i+1, title1[i], b1[i]]) 9 df1 = pd.DataFrame(lit1,columns=['排名', '名稱', '熱度']) 10 df1
1 #愛奇藝必看榜影視榜單 2 url="https://www.iqiyi.com/ranks1/-1/-6" 3 def getHTMLText(url,timeout=30): 4 try: 5 r=requests.get(url,timeout=30) #用requests抓取網頁信息 6 r.raise_for_status() #異常捕捉 7 r.encoding=r.apparent_encoding 8 return r.text 9 except: 10 return'產生異常' 11 html=getHTMLText(url) 12 soup=BeautifulSoup(html,'html.parser') 13 print(soup.prettify()) 14 r=requests.get(url) 15 r.encoding=r.apparent_encoding 16 html = r.text 17 soup = BeautifulSoup(html,'lxml') 18 print(soup.prettify()) 19 title2=[] 20 for i in soup.find_all('div', class_='rvi__tit1'): 21 title2.append(i.get_text().strip()) 22 title2 23 b2=[] 24 for i in soup.find_all('span', 25 class_='rvi__index__num'): 26 b2.append(i.get_text().strip()) 27 b2 28 print('{:^50}'.format('愛奇藝必看榜')) 29 print('{:^5}\t{:^40}\t{:^10}'.format('排名', '名稱', '熱度')) 30 for i in range(25): 31 print('{:^5}\t{:^40}\t{:^10}'.format(i+1, title2[i], b2[i])) 32 lit2=[] 33 for i in range(25): 34 lit2.append([i+1, title2[i], b2[i]]) 35 df2 = pd.DataFrame(lit2,columns=['排名', '名稱', '熱度']) 36 df2
1 #對獲取的數據進行持久化存儲 2 df1= pd.DataFrame(lit1,columns=['排名','名稱','熱度']) 3 df1.to_excel('D:/python/python1.xlsx') 4 df2= pd.DataFrame(lit2,columns=['排名','名稱','熱度']) 5 df2.to_excel('D:/python/python2.xlsx')
1 #讀取熱播榜excel文件 2 rank1=pd.DataFrame(pd.read_excel('D:/python/python1.xlsx')) 3 print(rank1)
1 #讀取必看榜excel文件 2 rank2=pd.DataFrame(pd.read_excel('D:/python/python2.xlsx')) 3 print(rank2)
1 #數據清 2 #1.刪除無效列 3 rank1.drop('名稱',axis=1,inplace=True) 4 print(rank1) 5 rank2.drop('名稱',axis=1,inplace=True) 6 print(rank2)
1 #2.檢查是否有重復值 2 print(rank1.duplicated()) 3 print(rank2.duplicated())
1 #3.檢查是否有空值 2 print(rank1['熱度'].isnull().value_counts()) 3 print(rank2['熱度'].isnull().value_counts())
1 #4.異常值處理 2 print(rank1.describe()) 3 print(rank2.describe())
1 #數據分析 2 from sklearn.linear_model import LinearRegression 3 X = df1.drop("名稱",axis=1) 4 predict_model = LinearRegression() 5 predict_model.fit(X,df1['熱度']) 6 print("回歸系數為:",predict_model.coef_) 7 X = df2.drop("名稱",axis=1) 8 predict_model = LinearRegression() 9 predict_model.fit(X,df2['熱度']) 10 print("回歸系數為:",predict_model.coef_)
1 #繪制排名與熱度的回歸圖 2 import seaborn as sns 3 plt.rcParams['font.sans-serif'] = ['SimHei'] 4 plt.rcParams['axes.unicode_minus'] = False 5 sns.regplot(rank1.排名,rank1.熱度,label="熱播榜") 6 sns.regplot(rank2.排名,rank2.熱度,label="必看榜")
1 #畫出散點圖 2 # 用來正常顯示中文標簽 3 plt.rcParams['font.sans-serif'] = ['SimHei'] 4 # 用來正常顯示負號 5 plt.rcParams['axes.unicode_minus'] = False 6 N=10 7 x=np.random.rand(N) 8 y=np.random.rand(N) 9 size=50 10 plt.xlabel("排名") 11 plt.ylabel("熱度") 12 plt.scatter(x,y,size,color='r',alpha=0.5,marker="o")
1 #散點圖 kind='reg' 2 sns.jointplot(x="排名",y="熱度", 3 data=rank1,kind='reg',color='g') 4 sns.jointplot(x="排名",y="熱度", 5 data=rank2,kind='reg',color='r')
1 # kind='hex' 2 sns.jointplot(x="排名",y="熱度", 3 data=rank1,kind='hex',color='g') 4 sns.jointplot(x="排名",y="熱度", 5 data=rank2,kind='hex',color='r')
1 # kind='kde' 2 sns.jointplot(x="排名",y="熱度", 3 data=rank1,kind="kde",space=0,color='g') 4 sns.jointplot(x="排名",y="熱度", 5 data=rank2,kind="kde",space=0,color='r')
1 #選擇排名和最高熱度兩個特征變量,繪制分布圖,用最小二乘法分析兩個變量間的二次擬合方程和擬合曲線 2 colnames=[" ","排名","名稱","最高熱度"] 3 df1 = pd.read_excel('D:/python/python1.xlsx',skiprows=1,names=colnames) 4 df2 = pd.read_excel('D:/python/python2.xlsx',skiprows=1,names=colnames) 5 6 X1 = df1.排名 7 Y1 = df1.最高熱度 8 Z1 = df1.名稱 9 10 X2 = df2.排名 11 Y2 = df2.最高熱度 12 Z2 = df2.名稱 13 #最高熱度與排名關系圖 14 matplotlib.rcParams['font.sans-serif']=['SimHei'] 15 plt.plot(X1,Y1,color="g", linewidth=2,label="熱播榜") 16 plt.plot(X2,Y2,color="r", linewidth=2,label="必看榜") 17 plt.legend(loc=1) 18 plt.xlabel("排名") 19 plt.ylabel("熱度") 20 plt.title('熱度與排名關系圖') 21 plt.show()
1 #最高熱度與排名柱狀關系圖 2 plt.bar(X2,Y2,color="r", linewidth=2,label="必看榜") 3 plt.bar(X1,Y1,color="g", linewidth=2,label="熱播榜") 4 plt.legend(loc=1) 5 plt.xlabel("排名") 6 plt.ylabel("熱度") 7 plt.title('熱度與排名柱狀關系圖') 8 plt.show()
1 #畫出散點圖 2 def A(): 3 plt.scatter(X1,Y1,color="g" 4 ,linewidth=2,label='必看榜') 5 plt.scatter(X2,Y2,color="r" 6 ,linewidth=2,label='熱播榜') 7 plt.legend(loc=1) 8 plt.title("散點圖",color="blue") 9 plt.grid() 10 plt.xlabel("排名") 11 plt.ylabel("最高熱度") 12 plt.show() 13 14 def func(p,x): 15 a,b,c=p 16 return a*x*x+b*x+c 17 18 def error(p,x,y): 19 return func(p,x)-y 20 21 print(A())
1 def main1(): 2 plt.figure(figsize=(10,6)) 3 p0=[0,0,0] 4 Para = leastsq(error,p0,args=(X1,Y1)) 5 a,b,c=Para[0] 6 print("a=",a,"b=",b,"c=",c) 7 plt.scatter(X1,Y1,color="g", 8 linewidth=2,label='必看榜熱度值分布') 9 plt.legend(loc=1) 10 x1=np.linspace(0,20,20) 11 y1=a*x1*x1+b*x1+c 12 plt.plot(x1,y1,color="red", 13 linewidth=2,label="必看榜擬合曲線") 14 plt.legend(loc=1) 15 plt.title("必看榜一元二次方程關系圖") 16 plt.xlabel("排名") 17 plt.ylabel("熱度") 18 plt.grid() 19 plt.show() 20 21 print(main1())
1 def main2(): 2 plt.figure(figsize=(10,6)) 3 p0=[0,0,0] 4 Para = leastsq(error,p0,args=(X2,Y2)) 5 a,b,c=Para[0] 6 print("a=",a,"b=",b,"c=",c) 7 plt.scatter(X2,Y2,color="blue", 8 linewidth=2,label='熱播榜熱度值分布') 9 plt.legend(loc=1) 10 x2=np.linspace(0,20,20) 11 y2=a*x2*x2+b*x2+c 12 plt.plot(x2,y2,color="red", 13 linewidth=2,label="熱播榜擬合曲線") 14 plt.legend(loc=1) 15 plt.title("熱播榜一元二次方程關系圖") 16 plt.xlabel("排名") 17 plt.ylabel("熱度") 18 plt.grid() 19 plt.show() 20 print(main2())
四、全部代碼
1 #導入庫 2 import requests 3 import pandas as pd 4 import numpy as np 5 import matplotlib.pyplot as plt 6 import matplotlib 7 import csv 8 import scipy as sp 9 import seaborn as sns 10 from sklearn.linear_model import LinearRegression 11 from bs4 import BeautifulSoup 12 from pandas import DataFrame 13 from scipy.optimize import leastsq 14 15 #填入要請求的服務器地址 16 url="https://www.iqiyi.com/ranks1/-1/0"#愛奇藝影視榜單 17 18 #requests抓取網頁信息 19 def getHTMLText(url,timeout=30): 20 try: 21 r=requests.get(url,timeout=30) #用requests抓取網頁信息 22 r.raise_for_status() #異常捕捉 23 r.encoding=r.apparent_encoding 24 return r.text 25 except: 26 return'產生異常' 27 28 #html.parser表示用BeautifulSoup庫解析網頁 29 html=getHTMLText(url) 30 soup=BeautifulSoup(html,'html.parser') 31 32 print(soup.prettify()) 33 #按照標准縮進格式的結構輸出 34 r=requests.get(url) 35 #請求網絡 36 r.encoding=r.apparent_encoding 37 #統一編碼 38 html = r.text 39 soup = BeautifulSoup(html,'lxml') 40 #type(soup) 41 print(soup.prettify()) 42 #基於bs4庫HTML的格式輸出,讓頁面更友好的顯示 43 #獲取標題 44 title1=[] 45 for i in soup.find_all('div', 46 class_='rvi__tit1'): 47 title1.append(i.get_text().strip()) 48 #獲取熱度 49 b1=[] 50 for i in soup.find_all('span', 51 class_='rvi__index__num'): 52 b1.append(i.get_text().strip()) 53 #整合獲取內容 54 print('{:^50}'.format('愛奇藝熱播榜')) 55 print('{:^5}\t{:^40}\t{:^10}'.format('排名', '名稱', '熱度')) 56 for i in range(25): 57 print('{:^5}\t{:^40}\t{:^10}'.format(i+1, title1[i], b1[i])) 58 lit1=[] 59 for i in range(25): 60 lit1.append([i+1, title1[i], b1[i]]) 61 df1 = pd.DataFrame(lit1,columns=['排名', '名稱', '熱度']) 62 #愛奇藝熱播榜影視榜單 63 url="https://www.iqiyi.com/ranks1/-1/-6" 64 def getHTMLText(url,timeout=30): 65 try: 66 r=requests.get(url,timeout=30) #用requests抓取網頁信息 67 r.raise_for_status() #異常捕捉 68 r.encoding=r.apparent_encoding 69 return r.text 70 except: 71 return'產生異常' 72 html=getHTMLText(url) 73 soup=BeautifulSoup(html,'html.parser') 74 print(soup.prettify()) 75 r=requests.get(url) 76 r.encoding=r.apparent_encoding 77 html = r.text 78 soup = BeautifulSoup(html,'lxml') 79 print(soup.prettify()) 80 title2=[] 81 for i in soup.find_all('div', class_='rvi__tit1'): 82 title2.append(i.get_text().strip()) 83 b2=[] 84 for i in soup.find_all('span', 85 class_='rvi__index__num'): 86 b2.append(i.get_text().strip()) 87 print('{:^50}'.format('愛奇藝必看榜')) 88 print('{:^5}\t{:^40}\t{:^10}'.format('排名', '名稱', '熱度')) 89 for i in range(25): 90 print('{:^5}\t{:^40}\t{:^10}'.format(i+1, title2[i], b2[i])) 91 lit2=[] 92 for i in range(25): 93 lit2.append([i+1, title2[i], b2[i]]) 94 df2 = pd.DataFrame(lit2,columns=['排名', '名稱', '熱度']) 95 #對獲取的數據進行持久化存儲 96 df1= pd.DataFrame(lit1,columns=['排名','名稱','熱度']) 97 df1.to_excel('D:/python/python1.xlsx') 98 df2= pd.DataFrame(lit2,columns=['排名','名稱','熱度']) 99 df2.to_excel('D:/python/python2.xlsx') 100 #讀取必看榜excel文件 101 rank1=pd.DataFrame(pd.read_excel('D:/python/python1.xlsx')) 102 #讀取熱播榜excel文件 103 rank2=pd.DataFrame(pd.read_excel('D:/python/python2.xlsx')) 104 #數據清 105 #1.刪除無效列 106 rank1.drop('名稱',axis=1,inplace=True) 107 rank2.drop('名稱',axis=1,inplace=True) 108 #2.檢查是否有重復值 109 print(rank1.duplicated()) 110 print(rank2.duplicated()) 111 #3.檢查是否有空值 112 print(rank1['熱度'].isnull().value_counts()) 113 print(rank2['熱度'].isnull().value_counts()) 114 #4.異常值處理 115 print(rank1.describe()) 116 print(rank2.describe()) 117 #數據分析 118 from sklearn.linear_model import LinearRegression 119 X = df1.drop("名稱",axis=1) 120 predict_model = LinearRegression() 121 predict_model.fit(X,df1['熱度']) 122 print("回歸系數為:",predict_model.coef_) 123 X = df2.drop("名稱",axis=1) 124 predict_model = LinearRegression() 125 predict_model.fit(X,df2['熱度']) 126 print("回歸系數為:",predict_model.coef_) 127 #繪制排名與熱度的回歸圖 128 import seaborn as sns 129 plt.rcParams['font.sans-serif'] = ['SimHei'] 130 plt.rcParams['axes.unicode_minus'] = False 131 sns.regplot(rank1.排名,rank1.熱度,label="熱播榜") 132 sns.regplot(rank2.排名,rank2.熱度,label="必看榜") 133 plt.legend(loc=1) 134 #畫出散點圖 135 # 用來正常顯示中文標簽 136 plt.rcParams['font.sans-serif'] = ['SimHei'] 137 # 用來正常顯示負號 138 plt.rcParams['axes.unicode_minus'] = False 139 N=10 140 x=np.random.rand(N) 141 y=np.random.rand(N) 142 size=50 143 plt.xlabel("排名") 144 plt.ylabel("熱度") 145 plt.scatter(x,y,size,color='r',alpha=0.5,marker="o") 146 #散點圖 kind='reg' 147 sns.jointplot(x="排名",y="熱度", 148 data=rank1,kind='reg',color='g') 149 sns.jointplot(x="排名",y="熱度", 150 data=rank2,kind='reg',color='r') 151 # kind='hex' 152 sns.jointplot(x="排名",y="熱度", 153 data=rank1,kind='hex',color='g') 154 sns.jointplot(x="排名",y="熱度", 155 data=rank2,kind='hex',color='r') 156 # kind='kde' 157 sns.jointplot(x="排名",y="熱度", 158 data=rank1,kind="kde",space=0,color='g') 159 sns.jointplot(x="排名",y="熱度", 160 data=rank2,kind="kde",space=0,color='r') 161 #選擇排名和最高熱度兩個特征變量,繪制分布圖,用最小二乘法分析兩個變量間的二次擬合方程和擬合曲線 162 colnames=[" ","排名","名稱","最高熱度"] 163 df1 = pd.read_excel('D:/python/python1.xlsx',skiprows=1,names=colnames) 164 df2 = pd.read_excel('D:/python/python2.xlsx',skiprows=1,names=colnames) 165 166 X1 = df1.排名 167 Y1 = df1.最高熱度 168 Z1 = df1.名稱 169 170 X2 = df2.排名 171 Y2 = df2.最高熱度 172 Z2 = df2.名稱 173 #最高熱度與排名關系圖 174 matplotlib.rcParams['font.sans-serif']=['SimHei'] 175 plt.plot(X1,Y1,color="g", linewidth=2,label="熱播榜") 176 plt.plot(X2,Y2,color="r", linewidth=2,label="必看榜") 177 plt.legend(loc=1) 178 plt.xlabel("排名") 179 plt.ylabel("熱度") 180 plt.title('熱度與排名關系圖') 181 plt.show() 182 #最高熱度與排名柱狀關系圖 183 plt.bar(X2,Y2,color="r", linewidth=2,label="必看榜") 184 plt.bar(X1,Y1,color="g", linewidth=2,label="熱播榜") 185 plt.legend(loc=1) 186 plt.xlabel("排名") 187 plt.ylabel("熱度") 188 plt.title('熱度與排名柱狀關系圖') 189 plt.show() 190 #畫出散點圖 191 def A(): 192 plt.scatter(X1,Y1,color="g" 193 ,linewidth=2,label='必看榜') 194 plt.scatter(X2,Y2,color="r" 195 ,linewidth=2,label='熱播榜') 196 plt.legend(loc=1) 197 plt.title("散點圖",color="blue") 198 plt.grid() 199 plt.xlabel("排名") 200 plt.ylabel("最高熱度") 201 plt.show() 202 203 def func(p,x): 204 a,b,c=p 205 return a*x*x+b*x+c 206 207 def error(p,x,y): 208 return func(p,x)-y 209 210 print(A()) 211 def main1(): 212 plt.figure(figsize=(10,6)) 213 p0=[0,0,0] 214 Para = leastsq(error,p0,args=(X1,Y1)) 215 a,b,c=Para[0] 216 print("a=",a,"b=",b,"c=",c) 217 plt.scatter(X1,Y1,color="g", 218 linewidth=2,label='必看榜熱度值分布') 219 plt.legend(loc=1) 220 x1=np.linspace(0,20,20) 221 y1=a*x1*x1+b*x1+c 222 plt.plot(x1,y1,color="red", 223 linewidth=2,label="必看榜擬合曲線") 224 plt.legend(loc=1) 225 plt.title("必看榜一元二次方程關系圖") 226 plt.xlabel("排名") 227 plt.ylabel("熱度") 228 plt.grid() 229 plt.show() 230 print(main1()) 231 232 def main2(): 233 plt.figure(figsize=(10,6)) 234 p0=[0,0,0] 235 Para = leastsq(error,p0,args=(X2,Y2)) 236 a,b,c=Para[0] 237 print("a=",a,"b=",b,"c=",c) 238 plt.scatter(X2,Y2,color="blue", 239 linewidth=2,label='熱播榜熱度值分布') 240 plt.legend(loc=1) 241 x2=np.linspace(0,20,20) 242 y2=a*x2*x2+b*x2+c 243 plt.plot(x2,y2,color="red", 244 linewidth=2,label="熱播榜擬合曲線") 245 plt.legend(loc=1) 246 plt.title("熱播榜一元二次方程關系圖") 247 plt.xlabel("排名") 248 plt.ylabel("熱度") 249 plt.grid() 250 plt.show()
print(main2())
五、總結
1.經過對數據的分析和可視化,從回歸方程和擬合曲線可以看出散點大部分都落在曲線上,說明熱度是隨着排名的遞減而遞減的。又從散點圖可以看出熱播榜的熱度大部分停留在4-8千之間,必看榜的熱度大部分停留在9-1萬之間。必看榜的熱度明顯高於熱播榜的熱度。
2.在這次對愛奇藝排行榜的分析的過程中,我從中學會了不少函數及用法。很多次都卡在一個點上,絞盡腦汁去想解決問題的辦法,通過觀看b站的視頻,百度搜索等方法去找尋答案。這兩個星期來也養成了耐心和獨立思考的習慣,並且提高了我對Python的興趣。