爬取纵横小说网周票榜
一、选题背景:为了更直观的观察出现代人喜爱的小说类型,预期目标是将数据爬取后进行可视化
二.主题式网络主题式网络爬虫设计方案
1.爬虫名称:爬取纵横小说网周票榜
2.爬虫爬取的内容:爬取纵横小说网周票榜数据
3.网络爬虫设计方案概述:用requests库访问页面用get方法获取页面资源,登录页面对页面HTML进行分析,用beautifulsoup库获取并提取自己所需要的信息。再讲数据保存到CSV文件中,进行数据清洗,数据可视化分析,绘制数据图表,并用最小二乘法进行拟合分析。
三、主题页面的结构特征分析:
1.主题页面的结构与特征分析:通过观察页面HTML源代码,可以发现每个小说名称的标题都位于'div', class_="rank_d_b_name"标签的子标签中,而周票数位于'div', class_="rank_d_b_ticket"标签的子标签中,通过标签的关系进行遍历得到需要的内容。
2.Htmls 页面解析:



四、网络爬虫程序设计
1.数据爬取与存储
#获取网址 url = 'http://www.zongheng.com/rank/details.html?rt=1&d=1' def getHTMLText(url): try: #设置表头信息 header = {"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"} r = requests.get(url, headers=header, timeout=30) #请求时间30s # 解决乱码问题 r.raise_for_status() r.encoding=r.apparent_encoding #修改编码方式 return r.text except: return "" #若出现异常则会返回空字符串 #使用BeautifulSoup工具解析页面 html = getHTMLText(url) soup=BeautifulSoup(html,'html.parser') #爬取热搜小说名称 name = soup.find_all('div', class_="rank_d_b_name") #爬取小说月票数 poll = soup.find_all('div', class_="rank_d_b_ticket") print('{:^55}'.format('小说排行榜')) print('{:^5}\t{:^40}\t{:^10}'.format('排名','小说名称','周票数')) num = 20 list = [] for i in range(num): print('{:^5}\t{:^100}\t{:^30}'.format(i+1, name[i].text, poll[i].text)) list.append([i+1,name[i].text,poll[i].text]) df = pd.DataFrame(list,columns=['排名','小说名称','周票数']) rank = r'纵横中文网周票排行.xlsx' df.to_excel(rank)


2.
#读取文件 df=pd.DataFrame(pd.read_excel('纵横中文网周票排行榜.xlsx')) #输出信息 print(df.head())

3.
#开始进行数据清洗 #删除无效列与行 df.drop('小说名称', axis = 1, inplace = True) #输出数据前五行 df.head()

4.
#检查是否有重复值 df.duplicated()

5.
#检查是否有空值 print(df['周票数'].isnull().value_counts()) #若有则删除空值 df[df.isnull().values==True] df.corr()

6.
#异常值处理 print(df.describe())

7.
#数据分析 from sklearn.linear_model import LinearRegression X = df.drop("小说名称",axis=1) predict_model = LinearRegression() predict_model.fit(X,df['周票数']) print("回归系数为:",predict_model.coef_)

8.
#绘制排名与周票数的回归图 import seaborn as sns sns.regplot(df.排名,df.周票数) plt.title('排名周票数回归散点图')

9.
#绘制散点图 import matplotlib.pyplot as plt from scipy.optimize import leastsq import numpy as np %matplotlib inline 排名 = (df["排名"]) 周票数 = (df["周票数"]) plt.rcParams['font.sans-serif']=['SimHei'] #用于正常显示中文标签 plt.figure(figsize=(8,5)) plt.scatter(排名,周票数,color="b",label=u"样本数据",linewidth=2) #颜色、标签、线宽 plt.title("排名 ",color="red") plt.xlabel("排名") plt.ylabel("周票数") plt.legend() plt.grid() plt.show()

10.
#绘制柱状图 plt.figure() x=np.arange(0,20) y=df.loc['0':'20','周票数'] #选取画图数据范围 plt.bar(x, y,color='b') #图类型、颜色 plt.xlabel('排名') plt.ylabel('周票数') plt.title("周票榜周票数据") plt.show()

11.
# 绘制折线图 plt.figure() plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 x=np.arange(0,20) y=df.loc['0':'20','周票数'] #选取画图数据范围 plt.plot(x, y,'r-o',color='b') plt.xlabel('排名') plt.ylabel('周票数') plt.title("周票榜周票数据") plt.show()

12.
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 sns.jointplot(x="排名",y="周票数",data=df,kind='reg') # kind='hex' sns.jointplot(x="排名",y="周票数",data=df,kind='hex') # kind='kde' sns.jointplot(x="排名",y="周票数",data=df,kind="kde",space=0,color='b')



13.
#绘制盒图 def box(): plt.title('周票数与排名盒图') sns.boxplot(x='排名',y='周票数', data=df) box()

14.
# 绘制单核密度图 sns.kdeplot(df['周票数'])

15.根据排名与周票数数据之间的关系,分析两个变量拟合一元二次曲线,建立变量之间的回归方程
# 用最小二乘法得出一元二次拟合方程 import numpy as np from numpy import genfromtxt import scipy as sp import matplotlib.pyplot as plt from scipy.optimize import leastsq plt.figure(figsize=(13,6)) plt.scatter(排名,周票数,color=[0,0,0.8,0.4],label=u"样本数据",linewidth=2) plt.xlabel("排名") plt.ylabel("周票数") plt.legend() def func(p,x): a,b,c=p return a*(x**2)+(b*x)+c def er_func(p,x,y): return func(p,x)-y p0=[2,3,4] P=leastsq(er_func,p0,args=(排名,周票数)) a,b,c=P[0] x=np.linspace(0,55,100) y=a*(x**2)+(b*x)+c plt.plot(x,y,color=[0,0,0.8,0.4],label=u"拟合直线",linewidth=2) plt.scatter(x,y,color="c",label=u"样本数据",linewidth=2) plt.legend() plt.title('排名周票数回归曲线') plt.grid() plt.show()

16.将以上各部分的代码汇总,附上完整程序代码
1 from bs4 import BeautifulSoup 2 import bs4 3 import xlwt 4 import requests 5 import pandas as pd 6 from pandas import DataFrame 7 import seaborn as sns 8 import numpy as np 9 import matplotlib.pyplot as plt 10 from scipy.optimize import leastsq 11 from sklearn.linear_model import LinearRegression 12 from numpy import genfromtxt 13 import scipy as sp 14 15 #获取网址 16 url = 'http://www.zongheng.com/rank/details.html?rt=1&d=1' 17 def getHTMLText(url): 18 try: 19 #设置表头信息 20 header = {"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"} 21 r = requests.get(url, headers=header, timeout=30) #请求时间30s 22 # 解决乱码问题 23 r.raise_for_status() 24 r.encoding=r.apparent_encoding #修改编码方式 25 return r.text 26 except: 27 return "" #若出现异常则会返回空字符串 28 29 #使用BeautifulSoup工具解析页面 30 html = getHTMLText(url) 31 soup=BeautifulSoup(html,'html.parser') 32 #爬取热搜小说名称 33 name = soup.find_all('div', class_="rank_d_b_name") 34 #爬取小说月票数 35 poll = soup.find_all('div', class_="rank_d_b_ticket") 36 print('{:^55}'.format('小说排行榜')) 37 print('{:^5}\t{:^40}\t{:^10}'.format('排名','小说名称','周票数')) 38 num = 20 39 list = [] 40 for i in range(num): 41 print('{:^5}\t{:^100}\t{:^30}'.format(i+1, name[i].text, poll[i].text)) 42 list.append([i+1,name[i].text,poll[i].text]) 43 df = pd.DataFrame(list,columns=['排名','小说名称','周票数']) 44 rank = r'纵横中文网周票排行.xlsx' 45 df.to_excel(rank) 46 47 #读取文件 48 df=pd.DataFrame(pd.read_excel('纵横中文网周票排行榜.xlsx')) 49 50 #输出信息 51 print(df.head()) 52 53 #开始进行数据清洗 54 #删除无效列与行 55 df.drop('小说名称', axis = 1, inplace = True) 56 57 #输出数据前五行 58 df.head() 59 60 #检查是否有重复值 61 df.duplicated() 62 63 #检查是否有空值 64 print(df['周票数'].isnull().value_counts()) 65 66 #若有则删除空值 67 df[df.isnull().values==True] 68 df.corr() 69 70 #异常值处理 71 print(df.describe()) 72 73 #数据分析 74 X = df.drop("小说名称",axis=1) 75 predict_model = LinearRegression() 76 predict_model.fit(X,df['周票数']) 77 print("回归系数为:",predict_model.coef_) 78 79 #绘制排名与周票数的回归图 80 sns.regplot(df.排名,df.周票数) 81 plt.title('排名周票数回归散点图') 82 83 #绘制散点图 84 %matplotlib inline 85 排名 = (df["排名"]) 86 周票数 = (df["周票数"]) 87 plt.rcParams['font.sans-serif']=['SimHei'] #用于正常显示中文标签 88 plt.figure(figsize=(8,5)) 89 plt.scatter(排名,周票数,color="b",label=u"样本数据",linewidth=2) #颜色、标签、线宽 90 plt.title("排名 ",color="red") 91 plt.xlabel("排名") 92 plt.ylabel("周票数") 93 plt.legend() 94 plt.grid() 95 plt.show() 96 97 #绘制柱状图 98 plt.figure() 99 x=np.arange(0,20) 100 y=df.loc['0':'20','周票数'] #选取画图数据范围 101 plt.bar(x, y,color='b') #图类型、颜色 102 plt.xlabel('排名') 103 plt.ylabel('周票数') 104 plt.title("周票榜周票数据") 105 plt.show() 106 107 # 绘制折线图 108 plt.figure() 109 plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 110 x=np.arange(0,20) 111 y=df.loc['0':'20','周票数'] #选取画图数据范围 112 plt.plot(x, y,'r-o',color='b') 113 plt.xlabel('排名') 114 plt.ylabel('周票数') 115 plt.title("周票榜周票数据") 116 plt.show() 117 118 plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 119 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 120 121 sns.jointplot(x="排名",y="周票数",data=df,kind='reg') 122 # kind='hex' 123 sns.jointplot(x="排名",y="周票数",data=df,kind='hex') 124 # kind='kde' 125 sns.jointplot(x="排名",y="周票数",data=df,kind="kde",space=0,color='b') 126 127 #绘制盒图 128 def box(): 129 plt.title('周票数与排名盒图') 130 sns.boxplot(x='排名',y='周票数', data=df) 131 box() 132 133 # 绘制单核密度图 134 sns.kdeplot(df['周票数']) 135 136 # 用最小二乘法得出一元二次拟合方程 137 plt.figure(figsize=(13,6)) 138 plt.scatter(排名,周票数,color=[0,0,0.8,0.4],label=u"样本数据",linewidth=2) 139 plt.xlabel("排名") 140 plt.ylabel("周票数") 141 plt.legend() 142 143 def func(p,x): 144 a,b,c=p 145 146 return a*(x**2)+(b*x)+c 147 148 def er_func(p,x,y): 149 150 return func(p,x)-y 151 152 p0=[2,3,4] 153 P=leastsq(er_func,p0,args=(排名,周票数)) 154 a,b,c=P[0] 155 x=np.linspace(0,55,100) 156 y=a*(x**2)+(b*x)+c 157 158 plt.plot(x,y,color=[0,0,0.8,0.4],label=u"拟合直线",linewidth=2) 159 plt.scatter(x,y,color="c",label=u"样本数据",linewidth=2) 160 plt.legend() 161 plt.title('排名周票数回归曲线') 162 plt.grid() 163 plt.show()
五、总结
1.经过对数据的分析和可视化,从回归方程和拟合曲线可以看出散点大部分都落在曲线上,说明周票数是随着排名的递增而递增的,数据的可视化与图表可以清晰明了的将数据的关系体现出来,让我们直观的了解周票数和排名的变化。
2.在这次对纵横小说网的爬虫中,我学会了不少函数的用法,最开始不会提取数据,感觉到非常的无解,通过b站以及CSDN中的资料进行解决,也是通过这次设计我很好的学习了BeautifulSoup库的使用,并将它初步熟练掌握。BeautifulSoup库在用于HTML解析和提取相关信息方面是非常优秀的,BeautifulSoup库的掌握对我今后的爬虫设计上也是非常有用的,不断的学习,使我养成有耐心和遇到困难想办法解决的好习惯,对于我的学习生涯具有很大的帮助
浙公网安备 33010602011771号