------主题式网络主题式网络爬虫设计方案------
1.爬虫名称:爬取微博热搜
2.爬虫爬取的内容:爬取微博热搜数据。 数据特征分析:各数据分布紧密联系。
3.网络爬虫设计方案概述:
实现思路:通过访问网页源代码使用xpath正则表达爬取数据,对数据进行保存数据,再对数据进行清洗和处理,数据分析与可视化处理。
技术难点:在编程的过程中,若中间部分出现错误,可能导致整个代码需要重新修改。数据实时更新,会导致部分上传的图形不一致。
------主题页面的结构特征分析------
1.主题页面的结构和特征分析:爬取数据都分布在标签'div.cc-cd-cb nano has-scrollbar'里面,标题标签为'span.t',热度标签为'span.e'。
2.Htmls页面解析:
3.节点(标签)查找方法与遍历方法:通过xpath遍历标签。利用xpath正则表达查找。
------网络爬虫程序设计------
1.数据爬取与采集:
url = "https://tophub.today/" headers = {'User-Agent':'2020'}#伪标题 response = requests.get(url,headers = headers)#发送get请求 #print(response.text)#获取源代码 xp = response.content.decode('utf-8')#配置编码 html = etree.HTML(xp)#构建一个xpath解析对象 div = html.xpath("//div[@id='node-1']/div") for a in div:#遍历标签 titles = a.xpath(".//span[@class='t']/text()")#xpath正则表达 numbers = a.xpath(".//span[@class='e']/text()")#xpath正则表达 b = []#创建一个空列表 for i in range(25): b.append([i+1,titles[i],numbers[i][:-2]])#拷贝前25组数据 file = pd.DataFrame(b,columns = ['排名','今日热搜','热度(单位为万)']) print(file) file.to_csv('微博热搜榜热度数据.csv')#保存文件,数据持久化
2.对数据进行清洗和处理:
#读取csv文件 df = pd.DataFrame(pd.read_csv('微博热搜榜热度数据.csv')) df.head()
#删除无效列与行 df.drop('今日热搜', axis=1, inplace=True) df.head()
#空值处理 df.isnull().sum()#返回0,表示没有空值
#缺失值处理 df[df.isnull().values==True]#返回无缺失值
#用describe()命令显示描述性统计指标 df.describe()
3.数据分析与可视化:
#用corr()显示各数据间的相关系数 df.corr()
#用seabron.lmplot()方法,建立排名和热度(单位为万)之间的线性关系 sns.lmplot(x='排名',y='热度(单位为万)',data=df)
#绘制排名与热度条形图 def one(): file_path = "'微博热搜榜热度数据.csv'" x = df['排名'] y = df['热度(单位为万)'] plt.xlabel('排名') plt.ylabel('热度(单位为万)') plt.bar(x,y) plt.title("绘制排名与热度条形图") plt.show() one()
#绘制排名与热度折线图 def two(): x = df['排名'] y = df['热度(单位为万)'] plt.xlabel('排名') plt.ylabel('热度(单位为万)') plt.plot(x,y) plt.scatter(x,y) plt.title("绘制排名与热度折线图") plt.show()
two()
#绘制排名与热度散点图 def three(): x = df['排名'] y = df['热度(单位为万)'] plt.xlabel('排名') plt.ylabel('热度(单位为万)') plt.scatter(x,y,color="red",label=u"热度分布数据",linewidth=2) plt.title("绘制排名与热度散点图") plt.legend() plt.show() three()
4.根据数据之间的关系,分析两个变量之间的相关系数,画出散点图,并建立变量之间的回归方程:
一元一次回归方程:
def main(): colnames = ["排名","今日热搜","number"] #由于运行存在问题,用number表示'热度(单位为万)' f = pd.read_csv('微博热搜榜热度数据.csv',skiprows=1,names=colnames) X = f.排名 Y = f.number def func(p,x): k,b = p return k*x+b def error_func(p,x,y): return func(p,x)-y p0 = [1,20] Para = leastsq(error_func,p0,args = (X,Y)) k,b = Para[0] print("k=",k,"b=",b) plt.figure(figsize=(8,6)) plt.scatter(X,Y,color="green",label=u"热度分布",linewidth=2) x=np.linspace(0,30,25) 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()
5.将以上各部分的代码汇总,附上完整程序代码:
1 import requests 2 from lxml import etree 3 import pandas as pd 4 import numpy as np 5 import matplotlib.pyplot as plt 6 import matplotlib 7 from scipy.optimize import leastsq 8 import scipy.stats as sts 9 import seaborn as sns 10 11 url = "https://tophub.today/" 12 headers = {'User-Agent':'2020'}#伪标题 13 html = requests.get(url,headers = headers)#发送get请求 14 #print(html.text)#获取源代码 15 16 html = html.content.decode('utf-8')#配置编码 17 html = etree.HTML(html)#构建一个xpath解析对象 18 19 div = html.xpath("//div[@id='node-1']/div") 20 for a in div:#遍历标签 21 titles = a.xpath(".//span[@class='t']/text()")#xpath正则表达 22 numbers = a.xpath(".//span[@class='e']/text()")#xpath正则表达 23 24 b = []#创建一个空列表 25 for i in range(25): 26 b.append([i+1,titles[i],numbers[i][:-2]])#拷贝前25组数据 27 file = pd.DataFrame(b,columns = ['排名','今日热搜','热度(单位为万)']) 28 #print(file) 29 file.to_csv('微博热搜榜热度数据.csv')#保存文件,数据持久化 30 31 #读取csv文件 32 df = pd.DataFrame(pd.read_csv('微博热搜榜热度数据.csv')) 33 df.head() 34 35 #删除无效列与行 36 df.drop('今日热搜', axis = 1, inplace = True) 37 df.head() 38 39 #空值处理 40 df.isnull().sum()#返回0,表示没有空值 41 42 43 #缺失值处理 44 df[df.isnull().values==True]#返回无缺失值 45 46 #用corr()显示各数据间的相关系数 47 df.corr() 48 49 plt.rcParams['font.sans-serif']=['STSong'] 50 51 #用seabron.lmplot()方法,建立排名和热度(单位为万)之间的线性关系 52 sns.lmplot(x='排名',y='热度(单位为万)',data=df) 53 54 #绘制排名与热度条形图 55 def one(): 56 file_path = "'微博热搜榜热度数据.csv'" 57 x = df['排名'] 58 y = df['热度(单位为万)'] 59 plt.xlabel('排名') 60 plt.ylabel('热度(单位为万)') 61 plt.bar(x,y) 62 plt.title("绘制排名与热度条形图") 63 plt.show() 64 one() 65 66 #绘制排名与热度折线图 67 def two(): 68 x = df['排名'] 69 y = df['热度(单位为万)'] 70 plt.xlabel('排名') 71 plt.ylabel('热度(单位为万)') 72 plt.plot(x,y) 73 plt.scatter(x,y) 74 plt.title("绘制排名与热度折线图") 75 plt.show() 76 two() 77 78 #绘制排名与热度散点图 79 def three(): 80 x = df['排名'] 81 y = df['热度(单位为万)'] 82 plt.xlabel('排名') 83 plt.ylabel('热度(单位为万)') 84 plt.scatter(x,y,color="red",label=u"热度分布数据",linewidth=2) 85 plt.title("绘制排名与热度散点图") 86 plt.legend() 87 plt.show() 88 three() 89 90 def main(): 91 colnames = ["排名","今日热搜","number"] #由于运行存在问题,用number表示'热度(单位为万)' 92 f = pd.read_csv('微博热搜榜热度数据.csv',skiprows=1,names=colnames) 93 X = f.排名 94 Y = f.number 95 r=sts.pearsonr(X,Y) #相关性 96 print("相关性计算结果",r) 97 def func(p,x): 98 k,b = p 99 return k*x+b 100 def error_func(p,x,y): 101 return func(p,x)-y 102 p0 = [1,20] 103 #使用leastsq()函数对数据进行拟合 104 Para = leastsq(error_func,p0,args = (X,Y)) 105 #读取结果 106 k,b = Para[0] 107 print("k=",k,"b=",b) 108 #画样本点 109 plt.figure(figsize=(8,6)) 110 plt.scatter(X,Y,color="green",label=u"热度分布",linewidth=2) 111 #画拟合直线 112 x=np.linspace(0,30,25) 113 y=k*x+b 114 plt.plot(x,y,color="red",label=u"回归方程直线",linewidth=2) 115 plt.title("微博今日热搜排名和热度关系图") 116 plt.xlabel('排名') 117 plt.ylabel('热度(单位为万)') 118 plt.legend() 119 plt.show() 120 main()
------结论------
1.经过对主题数据的分析与可视化,得到结论:通过数据分析可视化处理后,可以让我们更方便的了解到数据变化和趋势,缩短了人工对数据的处理和计算问题,解决了许多难以解决的问题。
2.小结:通过这次任务,我学会运用各类方法来处理数据,让编程变的没有那么复杂,进一步也体现出python的易学性。