一、选题背景
随着社会的发展、人类生活方式的变化,电影给我们的是生活的体验,是对人类生活的一种追溯。电影已经成为现代人类生活当中不可缺少的一部分。电影是人们无聊时的消遣,一部好的电影会使人陶醉其中,发泄我们的情绪,升华情感,让人翱翔在充满艺术与美的空间里。所以我通过爬取爱奇艺排行榜更好的了解当下人们的关注的电影
二、设计方案
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的兴趣。