对豆瓣读书排行的爬取以及数据分析
一、选题背景:为了更直观的观察出现代人喜爱的小图书类型,预期目标是将数据爬取后进行可视化
二.主题式网络主题式网络爬虫设计方案
1.爬虫名称:爬取豆瓣读书排行榜
2.爬虫爬取的内容:爬取纵横小说网周票榜数据
3.网络爬虫设计方案概述:用requests库访问页面用get方法获取页面资源,登录页面对页面HTML进行分析,用beautifulsoup库获取并提取自己所需要的信息。再讲数据保存到CSV文件中,进行数据清洗,数据可视化分析,绘制数据图表,并用最小二乘法进行拟合分析。
三、主题页面的结构特征分析:

1.主题页面的结构与特征分析:排行榜的内容为书名以及书籍信息,以及书的评分和评价人数
2.Htmls 页面解析:
发现我们需要爬取的信息都在<table width="100%">标签下,针对此我们编写爬虫程序
四、网络爬虫程序设计
1、以下为爬虫主程序,负责爬取网页中我们所需要的内容
1 import requests 2 from bs4 import BeautifulSoup 3 import re 4 import pandas as pd 5 import os 6 import numpy as np 7 import csv 8 import time 9 from sklearn.linear_model import LinearRegression 10 import matplotlib.pyplot as plt 11 import seaborn as sns 12 import matplotlib.pyplot as plt 13 import seaborn as sns 14 15 #导入库 16 17 titles = [] 18 nums = [] 19 peoples = [] 20 #定义列表 21 22 def get_book(url): 23 #定义爬虫程序 24 25 header = { 26 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62' 27 } 28 29 resp = requests.get(url,headers=header).text 30 #提取网页源代码 31 soup = BeautifulSoup(resp,"html.parser") 32 #倒入库 33 one = soup.findAll('table',{'width':'100%'}) 34 35 for i in one: 36 tit = i.find_all('a')[1].text 37 titles.append(tit) 38 #书名 39 num = i.find('span',{'class':'rating_nums'}).text 40 nums.append(num) 41 #评分 42 people = i.find('span',{'class':'pl'}).text 43 peoples.append(people) 44 #评价人数 45 #数据爬取 46 47 url = 'https://book.douban.com/top250?start={}' 48 urls = [url.format(num*25) for num in range(10)] 49 #构筑循环url 50 51 for link in urls: 52 get_book(link) 53 time.sleep(1) 54 #模拟人为操作 55 56 #url循环语句
2、接下来我们要对我们爬取的内容进行存储以便我们进行数据分析
num = 250 lst = [] for i in range(num): lst.append([i+1,titles[i],nums[i],peoples[i]]) df = pd.DataFrame(lst,columns=['排名','书名', '评分', '评价人数']) rank = r'rank.xlsx' df.to_excel(rank) #写入表 df = pd.DataFrame(pd.read_excel('rank.xlsx')) #pandas打开表 df.replace('\s+','',regex=True,inplace=True) #删除表中空格 df.to_excel('top250pandas.xlsx', sheet_name='bluewhale_cc') #导出处理后的表

3、接下来我们要对数据进行清洗以及处理
1 af = pd.DataFrame(pd.read_excel('top250.pandas.xlsx')) 2 #开始进行数据清洗 3 #删除无效列与行 4 af.drop('书名', axis = 1, inplace = True) 5 #输出数据前五行 6 af.head() 7 #检查是否有重复值 8 af.duplicated() 9 #检查是否有空值 10 print(af['评价人数'].isnull().value_counts()) 11 #若有则删除空值 12 df[df.isnull().values==True] 13 df.corr() 14 #异常值处理 15 print(af.describe())



4、接下来进行数据分析
散点图
1 #排名与评分的散点图 2 plt.rcParams['font.sans-serif'] = ['SimHei'] 3 plt.rcParams['axes.unicode_minus'] = False 4 # 数据准备 5 N = 1000 6 x = af['排名'] 7 y = af['评分'] 8 # 用Matplotlib画散点图 9 plt.scatter(x, y,marker='x') 10 plt.show() 11 12 #排名与评价人数的散点图 13 plt.rcParams['font.sans-serif'] = ['SimHei'] 14 plt.rcParams['axes.unicode_minus'] = False 15 N = 1000 16 x = af['排名'] 17 y = af['评价人数'] 18 # 用Matplotlib画散点图 19 plt.scatter(x, y,marker='x') 20 plt.show()


折线图
1 #排名与评分的折线图 2 plt.rcParams['font.sans-serif'] = ['SimHei'] 3 plt.rcParams['axes.unicode_minus'] = False 4 # 数据准备 5 x = af['排名'] 6 y = af['评分'] 7 # 使用Seaborn画折线图 8 df = pd.DataFrame({'x': x, 'y': y}) 9 sns.lineplot(x="x", y="y", data=df) 10 plt.show() 11 12 #排名与评价人数的折线图 13 plt.rcParams['font.sans-serif'] = ['SimHei'] 14 plt.rcParams['axes.unicode_minus'] = False 15 x = af['排名'] 16 y = af['评价人数'] 17 # 使用Seaborn画折线图 18 df = pd.DataFrame({'x': x, 'y': y}) 19 sns.lineplot(x="x", y="y", data=df) 20 plt.show()


直方图
1 #排名与评分的直方图 2 plt.rcParams['font.sans-serif'] = ['SimHei'] 3 plt.rcParams['axes.unicode_minus'] = False 4 # 数据准备 5 a = af['排名'] 6 s = af['评分'] 7 # 用Matplotlib画直方图 8 plt.hist(s) 9 plt.show() 10 11 #排名与评价人数的直方图 12 plt.rcParams['font.sans-serif'] = ['SimHei'] 13 plt.rcParams['axes.unicode_minus'] = False 14 # 数据准备 15 a = af['排名'] 16 s = af['评价人数'] 17 # 用Matplotlib画直方图 18 plt.hist(s) 19 plt.show()


条形图
1 #排名与评分的条形图 2 plt.rcParams['font.sans-serif'] = ['SimHei'] 3 plt.rcParams['axes.unicode_minus'] = False 4 x = af['排名'] 5 y = af['评分'] 6 # 用Matplotlib画条形图 7 plt.bar(x, y) 8 plt.show() 9 10 #排名与评价人数的条形图 11 plt.rcParams['font.sans-serif'] = ['SimHei'] 12 plt.rcParams['axes.unicode_minus'] = False 13 x = af['排名'] 14 y = af['评价人数'] 15 # 用Matplotlib画条形图 16 plt.bar(x, y) 17 plt.show()


回归方程分析
X = af.drop("书名",axis=1) predict_model = LinearRegression() predict_model.fit(X,df['评分']) print("回归系数为:",predict_model.coef_)

绘制回归方程图
colnames=[" ","排名","评价人数","评分"] X = af['排名'] Y = af['评价人数'] Z = af['评分'] def A(): plt.scatter(X,Y,color="blue",linewidth=2) plt.title("RM scatter",color="blue") plt.grid() plt.show() def B(): plt.scatter(X,Y,color="green",linewidth=2) plt.title("redu",color="blue") plt.grid() plt.show() def func(p,x): a,b,c=p return a*x*x+b*x+c def error(p,x,y): return func(p,x)-y def main(): plt.figure(figsize=(10,6)) p0=[0,0,0] Para = leastsq(error,p0,args=(X,Y)) a,b,c=Para[0] print("a=",a,"b=",b,"c=",c) plt.scatter(X,Y,color="blue",linewidth=2) x=np.linspace(0,20,20) y=a*x*x+b*x+c plt.plot(x,y,color="blue",linewidth=2,) plt.title("热度值分布") plt.grid() plt.show() print(A()) print(B()) print(main())

、
5、完整代码
1 import requests 2 from bs4 import BeautifulSoup 3 import re 4 import pandas as pd 5 import os 6 import numpy as np 7 import csv 8 import time 9 from sklearn.linear_model import LinearRegression 10 import matplotlib.pyplot as plt 11 import seaborn as sns 12 import matplotlib.pyplot as plt 13 import seaborn as sns 14 from matplotlib import pyplot as plt 15 from numpy import genfromtxt 16 import matplotlib.pyplot as plt 17 import matplotlib 18 from scipy.optimize import leastsq 19 #导入库 20 21 titles = [] 22 nums = [] 23 peoples = [] 24 #定义列表 25 26 def get_book(url): 27 #定义爬虫程序 28 29 header = { 30 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62' 31 } 32 33 resp = requests.get(url,headers=header).text 34 #提取网页源代码 35 36 soup = BeautifulSoup(resp,"html.parser") 37 #导入BeautifulSoup 38 39 one = soup.findAll('table',{'width':'100%'}) 40 41 for i in one: 42 tit = i.find_all('a')[1].text 43 titles.append(tit) 44 #书名 45 num = i.find('span',{'class':'rating_nums'}).text 46 nums.append(num) 47 #评分 48 people = i.find('span',{'class':'pl'}).text 49 peoples.append(people) 50 #评价人数 51 #数据爬取 52 53 url = 'https://book.douban.com/top250?start={}' 54 urls = [url.format(num*25) for num in range(10)] 55 #构筑循环url 56 57 for link in urls: 58 get_book(link) 59 time.sleep(1) 60 #模拟人为操作 61 62 #url循环语句 63 64 num = 250 65 lst = [] 66 for i in range(num): 67 lst.append([i+1,titles[i],nums[i],peoples[i]]) 68 df = pd.DataFrame(lst,columns=['排名','书名', '评分', '评价人数']) 69 rank = r'rank.xlsx' 70 df.to_excel(rank) 71 #写入表 72 73 df = pd.DataFrame(pd.read_excel('rank.xlsx')) 74 #pandas打开表 75 df.replace('\s+','',regex=True,inplace=True) 76 #删除表中空格 77 df.to_excel('top250pandas.xlsx', sheet_name='bluewhale_cc') 78 #导出处理后的表 79 af = pd.DataFrame(pd.read_excel('top250.pandas.xlsx')) 80 #开始进行数据清洗 81 #删除无效列与行 82 af.drop('书名', axis = 1, inplace = True) 83 #输出数据前五行 84 af.head() 85 #检查是否有重复值 86 af.duplicated() 87 #检查是否有空值 88 print(af['评价人数'].isnull().value_counts()) 89 #若有则删除空值 90 df[df.isnull().values==True] 91 df.corr() 92 #异常值处理 93 print(af.describe()) 94 #数据分析 95 96 X = af.drop("书名",axis=1) 97 predict_model = LinearRegression() 98 predict_model.fit(X,df['评分']) 99 print("回归系数为:",predict_model.coef_) 100 101 102 #排名与评分的散点图 103 plt.rcParams['font.sans-serif'] = ['SimHei'] 104 plt.rcParams['axes.unicode_minus'] = False 105 # 数据准备 106 N = 1000 107 x = af['排名'] 108 y = af['评分'] 109 # 用Matplotlib画散点图 110 plt.scatter(x, y,marker='x') 111 plt.show() 112 113 #排名与评价人数的散点图 114 plt.rcParams['font.sans-serif'] = ['SimHei'] 115 plt.rcParams['axes.unicode_minus'] = False 116 N = 1000 117 x = af['排名'] 118 y = af['评价人数'] 119 # 用Matplotlib画散点图 120 plt.scatter(x, y,marker='x') 121 plt.show() 122 123 #排名与评分的折线图 124 plt.rcParams['font.sans-serif'] = ['SimHei'] 125 plt.rcParams['axes.unicode_minus'] = False 126 # 数据准备 127 x = af['排名'] 128 y = af['评分'] 129 # 使用Seaborn画折线图 130 df = pd.DataFrame({'x': x, 'y': y}) 131 sns.lineplot(x="x", y="y", data=df) 132 plt.show() 133 134 #排名与评价人数的折线图 135 plt.rcParams['font.sans-serif'] = ['SimHei'] 136 plt.rcParams['axes.unicode_minus'] = False 137 x = af['排名'] 138 y = af['评价人数'] 139 # 使用Seaborn画折线图 140 df = pd.DataFrame({'x': x, 'y': y}) 141 sns.lineplot(x="x", y="y", data=df) 142 plt.show() 143 144 #排名与评分的直方图 145 plt.rcParams['font.sans-serif'] = ['SimHei'] 146 plt.rcParams['axes.unicode_minus'] = False 147 # 数据准备 148 a = af['排名'] 149 s = af['评分'] 150 # 用Matplotlib画直方图 151 plt.hist(s) 152 plt.show() 153 154 #排名与评价人数的直方图 155 plt.rcParams['font.sans-serif'] = ['SimHei'] 156 plt.rcParams['axes.unicode_minus'] = False 157 # 数据准备 158 a = af['排名'] 159 s = af['评价人数'] 160 # 用Matplotlib画直方图 161 plt.hist(s) 162 plt.show() 163 164 #排名与评分的条形图 165 plt.rcParams['font.sans-serif'] = ['SimHei'] 166 plt.rcParams['axes.unicode_minus'] = False 167 x = af['排名'] 168 y = af['评分'] 169 # 用Matplotlib画条形图 170 plt.bar(x, y) 171 plt.show() 172 173 #排名与评价人数的条形图 174 plt.rcParams['font.sans-serif'] = ['SimHei'] 175 plt.rcParams['axes.unicode_minus'] = False 176 x = af['排名'] 177 y = af['评价人数'] 178 # 用Matplotlib画条形图 179 plt.bar(x, y) 180 plt.show() 181 182 183 colnames=[" ","排名","评价人数","评分"] 184 X = af['排名'] 185 Y = af['评价人数'] 186 Z = af['评分'] 187 def A(): 188 plt.scatter(X,Y,color="blue",linewidth=2) 189 plt.title("RM scatter",color="blue") 190 plt.grid() 191 plt.show() 192 def B(): 193 plt.scatter(X,Y,color="green",linewidth=2) 194 plt.title("redu",color="blue") 195 plt.grid() 196 plt.show() 197 def func(p,x): 198 a,b,c=p 199 return a*x*x+b*x+c 200 def error(p,x,y): 201 return func(p,x)-y 202 def main(): 203 plt.figure(figsize=(10,6)) 204 p0=[0,0,0] 205 Para = leastsq(error,p0,args=(X,Y)) 206 a,b,c=Para[0] 207 print("a=",a,"b=",b,"c=",c) 208 plt.scatter(X,Y,color="blue",linewidth=2) 209 x=np.linspace(0,20,20) 210 y=a*x*x+b*x+c 211 plt.plot(x,y,color="blue",linewidth=2,) 212 plt.title("热度值分布") 213 plt.grid() 214 plt.show() 215 print(A()) 216 print(B()) 217 print(main())
6、总结
1、得出的结论
经过对数据的分析和可视化,从回归方程和拟合曲线可以看出散点大部分都落在曲线上,
说明评分是随着排名的递增而递增的,数据的可视化与图表可以清晰明了的将数据的关系体现出来,让我们直观的了解评分和排名的变化。
但是评价人数与书的排名关系并不完全正相关。
2、个人总结
在这次的爬虫编写中,我学会了不少函数的用法,也是通过这次设计我很好的学习了BeautifulSoup库的使用,并将它初步熟练掌握。BeautifulSoup库在用于HTML解析和提取相关信息方面是非常优秀的,BeautifulSoup库的掌握对我今后的爬虫设计上也是非常有用的,不断的学习,使我养成有耐心和遇到困难想办法解决的好习惯,对于我的学习生涯具有很大的帮助,通过此次数据集分析练习,我熟练并掌握了数据归纳,数据清洗与可视化相关操作。这次的程序设计也是在对于python的知识进行一个熟悉的过程,通过本次任务,我对代码的掌握程度得到了一定程度上的提升,并且在完成任务的过程中提高了自己对于分析代码的能力,也是为以后正式编写代码程序打下坚实的基础

浙公网安备 33010602011771号