爬取豆瓣电影前20
一.主题式网络主题式网络爬虫设计方案
1.爬虫名称:爬取豆瓣电影前20
2.爬虫爬取的内容:爬取豆瓣电影前20数据。
3.网络爬虫设计方案概述:
实现思路:通过访问网页源代码,使用soup.find_all正则表达爬取数据,对数据进行保存数据,再对数据进行清洗和处理,数据分析与可视化处理。
技术难点:经常爬不到所需要找的标签内容。
二、主题页面的结构特征分析
1.主题页面的结构与特征分析:主题页面访问网址为:'https://movie.douban.com/top250'
特征分析:电影名标签分布在span class="title"中,评分标签分布在span class="rating_num"中,电影介绍标签分布在span class="inq"中。
2.Htmls页面解析:
3.节点(标签)查找方法与遍历方法:通过遍历标签查找所需内容。
三、网络爬虫程序设计
1.数据爬取与采集:
1 from bs4 import BeautifulSoup 2 import pandas as pd 3 from sklearn.linear_model import LinearRegression 4 import seaborn as sns 5 import numpy as np 6 import matplotlib.pyplot as plt 7 import matplotlib 8 from scipy.optimize import leastsq 9 10 #定义爬虫函数 11 def get_html(url): 12 headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362'}#伪装爬虫 13 resp = requests.get(url, headers = headers) 14 return resp.text 15 16 url = 'https://movie.douban.com/top250' 17 html = get_html(url) 18 soup = BeautifulSoup(html, 'html.parser')#正则表达 19 20 21 a = soup.find_all('div', class_='hd') 22 #电影名 23 name = [] 24 for i in a: 25 name.append(i.a.span.text) 26 27 #评分 28 score = soup.find_all('span', class_='rating_num') 29 30 #介绍 31 introduce = soup.find_all('span', class_='inq') 32 33 lt = [] 34 #遍历前20 35 num = 20 36 for i in range(num): 37 lt.append([i+1,name[i], score[i].string, introduce[i].string]) 38 df = pd.DataFrame(lt,columns = ['排名', '电影名', '评分', '介绍']) 39 df.to_csv('豆瓣电影前20数据.csv') #保存文件,数据持久化
2.对数据进行清洗和处理
1 #读取csv文件 2 df = pd.DataFrame(pd.read_csv('豆瓣电影前20数据.csv')) 3 df.head()
#删除无效列与行 df.drop('介绍', axis=1, inplace = True) df.head()
#检查是否有重复值 df.duplicated()
#空值处理 df.isnull().sum()#返回0,表示没有空值
#缺失值处理 df[df.isnull().values==True]#返回无缺失值
#用describe()命令显示描述性统计指标 df.describe()
3.数据分析与可视化
#算出评分回归系数 X = df.drop("电影名",axis=1) predict_model = LinearRegression() predict_model.fit(X,df['评分']) print("回归系数为:",predict_model.coef_)
#绘制排名与评分的回归图 plt.rcParams['font.sans-serif']=['STSong'] sns.regplot(df.排名,df.评分)
# 绘制垂直柱状图 plt.rcParams['axes.unicode_minus']=False #用来正常显示负号 plt.bar(df.排名, df.评分, label="排名与评分柱状图") plt.show()
# 绘制散点图 def Scatter_point(): plt.scatter(df.排名, df.评分, color='blue', s=25, marker="o") plt.xlabel("排名") plt.ylabel("评分") plt.title("排名与评分散点图") plt.show() Scatter_point()
#绘制折线图 def point1(): x = df['排名'] y = df['评分'] plt.xlabel('排名') plt.ylabel('评分') plt.plot(x,y) plt.scatter(x,y) plt.title("绘制排名与评分折线图") plt.show() point1()
#绘制排名与评分箱体图 def point2(): plt.figure(figsize=(10, 6)) plt.title('绘制排名与评分箱体图') sns.boxplot(x='排名',y='评分', data=df) point2()
#绘制其它分布图 sns.jointplot(x="排名",y='评分',data = df, kind='kde', color='r') sns.jointplot(x="排名",y='评分',data = df) sns.jointplot(x="排名",y='评分',data = df, kind='reg') sns.jointplot(x="排名",y='评分',data = df, kind='hex')
4.根据数据之间的关系,分析两个变量之间的相关系数,画出散点图,并建立变量之间的回归方程
#绘制一元一次回归方程 def main(): colnames = ["排名", "电影名", "评分", "介绍"] df = pd.read_csv('豆瓣电影前20数据.csv',skiprows=1,names=colnames) X = df.排名 Y = df.评分 def func(p, x): k, b = p return k * x + b def error_func(p, x, y): return func(p,x)-y p0 = [0,0] Para = leastsq(error_func, p0, args = (X, Y)) k, b = Para[0] print("k=",k,"b=",b) plt.figure(figsize=(10,6)) plt.scatter(X,Y,color="green",label=u"评分分布",linewidth=2) x=np.linspace(0,30,20) y=k*x+b plt.plot(x,y,color="red",label=u"回归方程直线",linewidth=2) plt.title("电影排名和评分一元一次回归方程图") plt.xlabel('排名') plt.ylabel('评分') plt.legend() plt.show() main()
#绘制一元二次回归方程 def point1_2(): colnames = ["排名", "电影名", "评分", "介绍"] df = pd.read_csv('豆瓣电影数据.csv',skiprows=1,names=colnames) X = df.排名 Y = df.评分 def func(p,x): a,b,c=p return a*x*x+b*x+c def error_func(p,x,y): return func(p,x)-y p0=[0,0,0] Para=leastsq(error_func,p0,args=(X,Y)) a,b,c=Para[0] plt.figure(figsize=(10,6)) plt.scatter(X,Y,color="green",label=u"评分分布",linewidth=2) x=np.linspace(0,30,20) y=a*x*x+b*x+c plt.plot(x,y,color="red",label=u"拟合直线",linewidth=2) plt.title("电影排名和评分一元二次回归方程关系图") plt.legend() plt.show() point1_2()
5.数据持久化
1 df.to_csv('豆瓣电影前20数据.csv') #保存文件,数据持久化
6.将以上各部分的代码汇总,附上完整程序代码
1 ########################开始编程###################### 2 import requests 3 from bs4 import BeautifulSoup 4 import pandas as pd 5 from sklearn.linear_model import LinearRegression 6 import seaborn as sns 7 import numpy as np 8 import matplotlib.pyplot as plt 9 import matplotlib 10 from scipy.optimize import leastsq 11 12 #定义爬虫函数 13 def get_html(url): 14 headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362'}#伪装爬虫 15 resp = requests.get(url, headers = headers) 16 return resp.text 17 18 url = 'https://movie.douban.com/top250' 19 html = get_html(url) 20 soup = BeautifulSoup(html, 'html.parser')#正则表达 21 22 23 a = soup.find_all('div', class_='hd') 24 #电影名 25 name = [] 26 for i in a: 27 name.append(i.a.span.text) 28 29 #评分 30 score = soup.find_all('span', class_='rating_num') 31 32 #介绍 33 introduce = soup.find_all('span', class_='inq') 34 35 lt=[] 36 #遍历前20 37 num = 20 38 for i in range(num): 39 lt.append([i+1,name[i], score[i].string, introduce[i].string]) 40 df = pd.DataFrame(lt,columns = ['排名', '电影名', '评分', '介绍']) 41 df.to_csv('豆瓣电影前20数据.csv') #保存文件,数据持久化 42 43 #读取csv文件 44 df = pd.DataFrame(pd.read_csv('豆瓣电影前20数据.csv')) 45 df.head() 46 47 #删除无效列与行 48 df.drop('介绍', axis=1, inplace = True) 49 df.head() 50 51 #检查是否有重复值 52 df.duplicated() 53 54 #空值处理 55 df.isnull().sum()#返回0,表示没有空值 56 57 #缺失值处理 58 df[df.isnull().values==True]#返回无缺失值 59 60 #用describe()命令显示描述性统计指标 61 df.describe() 62 63 #算出评分回归系数 64 X = df.drop("电影名",axis=1) 65 predict_model = LinearRegression() 66 predict_model.fit(X,df['评分']) 67 print("回归系数为:",predict_model.coef_) 68 69 #绘制排名与评分的回归图 70 plt.rcParams['font.sans-serif']=['STSong'] 71 sns.regplot(df.排名,df.评分) 72 73 # 绘制垂直柱状图 74 plt.rcParams['axes.unicode_minus']=False #用来正常显示负号 75 plt.bar(df.排名, df.评分, label="排名与评分柱状图") 76 plt.show() 77 78 # 绘制散点图 79 def Scatter_point(): 80 81 plt.scatter(df.排名, df.评分, color='blue', s=25, marker="o") 82 plt.xlabel("排名") 83 plt.ylabel("评分") 84 plt.title("排名与评分散点图") 85 plt.show() 86 Scatter_point() 87 88 #绘制折线图 89 def point1(): 90 x = df['排名'] 91 y = df['评分'] 92 plt.xlabel('排名') 93 plt.ylabel('评分') 94 plt.plot(x,y) 95 plt.scatter(x,y) 96 plt.title("绘制排名与评分折线图") 97 plt.show() 98 point1() 99 100 #绘制排名与评分箱体图 101 def point2(): 102 plt.figure(figsize=(10, 6)) 103 plt.title('绘制排名与评分箱体图') 104 sns.boxplot(x='排名',y='评分', data=df) 105 point2() 106 107 #绘制其它分布图 108 sns.jointplot(x="排名",y='评分',data = df, kind='kde', color='r') 109 110 sns.jointplot(x="排名",y='评分',data = df) 111 112 sns.jointplot(x="排名",y='评分',data = df, kind='reg') 113 114 sns.jointplot(x="排名",y='评分',data = df, kind='hex') 115 116 #绘制一元一次回归方程 117 def main(): 118 colnames = ["排名", "电影名", "评分", "介绍"] 119 df = pd.read_csv('豆瓣电影前20数据.csv',skiprows=1,names=colnames) 120 X = df.排名 121 Y = df.评分 122 def func(p, x): 123 k, b = p 124 return k * x + b 125 def error_func(p, x, y): 126 return func(p,x)-y 127 p0 = [0,0] 128 Para = leastsq(error_func, p0, args = (X, Y)) 129 k, b = Para[0] 130 print("k=",k,"b=",b) 131 plt.figure(figsize=(10,6)) 132 plt.scatter(X,Y,color="green",label=u"评分分布",linewidth=2) 133 x=np.linspace(0,30,20) 134 y=k*x+b 135 plt.plot(x,y,color="red",label=u"回归方程直线",linewidth=2) 136 plt.title("电影排名和评分一元一次回归方程图") 137 plt.xlabel('排名') 138 plt.ylabel('评分') 139 plt.legend() 140 plt.show() 141 main() 142 #绘制一元二次回归方程 143 def point1_2(): 144 colnames = ["排名", "电影名", "评分", "介绍"] 145 df = pd.read_csv('豆瓣电影数据.csv',skiprows=1,names=colnames) 146 X = df.排名 147 Y = df.评分 148 def func(p,x): 149 a,b,c=p 150 return a*x*x+b*x+c 151 def error_func(p,x,y): 152 return func(p,x)-y 153 p0=[0,0,0] 154 Para=leastsq(error_func,p0,args=(X,Y)) 155 a,b,c=Para[0] 156 plt.figure(figsize=(10,6)) 157 plt.scatter(X,Y,color="green",label=u"评分分布",linewidth=2) 158 x=np.linspace(0,30,20) 159 y=a*x*x+b*x+c 160 plt.plot(x,y,color="red",label=u"拟合直线",linewidth=2) 161 plt.title("电影排名和评分一元二次回归方程关系图") 162 plt.legend() 163 plt.show() 164 point1_2() 165 ##########################编程结束######################
四、结论
1.经过对主题数据的分析与可视化,可以得到哪些结论?
经过对主题数据的分析与可视化,可以让我更直观的了解到表面上所呈现的数据,更能理解数据
2.对本次程序设计任务完成的情况做一个简单的小结。
在这次作业中,通过不断的对代码进行修改,让我加深了对python的掌握,通过这次作业,让我补足了我很多不足,让我收获良多