爱奇艺排行榜爬取及分析

一、选题背景

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

二、设计方案 

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的兴趣。

 

posted @ 2021-12-28 19:11  郑俊强  阅读(1203)  评论(0编辑  收藏  举报