爬取纵横小说网周票榜

一、选题背景:为了更直观的观察出现代人喜爱的小说类型,预期目标是将数据爬取后进行可视化

二.主题式网络主题式网络爬虫设计方案

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库的掌握对我今后的爬虫设计上也是非常有用的,不断的学习,使我养成有耐心和遇到困难想办法解决的好习惯,对于我的学习生涯具有很大的帮助

posted @ 2021-12-29 23:54  第三人称x  阅读(266)  评论(0)    收藏  举报