一、选题的背景
目前互联网发达,各种搜索引擎各有千秋,对百度热搜的分析,可以直观地看出每个热点之间的差距,得出热点关系之间的联系,以及热点关键词的关系.
二、主题式网络爬虫设计方案
1.主题式网络爬虫名称
《python爬虫之爬取百度热搜榜》
2.主题式网络爬虫爬取的内容与数据特征分析
爬取内容:"排名","热搜数据","标题"
数据特征分析:"排名"、"热度数据"的之间关系整体呈现上升的趋势,可通过后续绘制直方图、折线图等观察数据的变化情况。
3.主题式网络爬虫设计方案概述
实现思路:在浏览器 中通过F12访问网页源代码,,分析网站源代码,找到自己所需要的数据所在的位置,提取数据,对数据进行保存到相同路径csv文件中,读取改文件,进行数据清洗,数据模型分析,数据可视化处理,绘制分布图,用最小二乘法分析两个变量间的二次拟合方程和绘制拟合曲线。
技术难点:对库使用和库中函数的运用,爬取的内容的机构分析处理做数据分析,即求回归系数,因为标题是文字,无法与数字作比较,需要把标题这一列删除才可。由于不明原因,输出结果经常会显示超出列表范围。
三.主题页面的结构特征分析
1.主题页面的结构与特征分析:先寻找到热搜对应的网页代码,紧接着寻找排名,标题,热度数据所对应的class标签。
2.页面解析
1.
1 #输入所要爬取的网页 2 url="https://top.baidu.com/board?tab=realtime" 3 #伪装爬虫头避免被检测拦截 4 headers = {'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'} 5 #请求网站 6 r=requests.get(url) 7 #print(r.text) 8 #对页面内容重新编码 9 r.encoding=r.apparent_encoding 10 data=r.text 11 #使用BeautifulSoup 12 soup=BeautifulSoup(data,'html.parser') 13 #显示网站结构 14 #print(soup.prettify()) 15 head=[] 16 index=[] 17 for i in soup.find_all(class_="hot-index_1Bl1a"): 18 head.append(i.get_text().strip()) 19 for i in soup.find_all(class_="c-single-text-ellipsis"): 20 index.append(i.get_text().strip()) 21 data=[head,index] 22 s=pd.DataFrame(data,index=["标题","热度数据"]) 23 #将所得数据进行可视化 24 print(s.T)
2.
1 #将数据保存至本地并进行数据的清理 2 S="F:\各种工作杂碎东西\\baidu1.csv" 3 df=pd.DataFrame(data,index=["标题","热度数据"]) 4 df.T.to_csv(S,encoding="utf_8_sig")
1 #清洗数据 2 #有表头读入 3 df = pd.read_csv('F:\各种工作杂碎东西\\baidu1.csv') 4 #修改表头 5 df = pd.read_csv('F:\各种工作杂碎东西\\baidu1.csv',header=None,names=['排名','热度数据','标题']) 6 #调整排名 7 df=df.drop([0]) 8 for i in range(31): 9 df['排名'].loc[i] =i 10 df
3.
1 #检查是否有重复值 print(df.duplicated())
4.
1 #检查是否有空值 2 print(df['热度数据'].isnull().value_counts())
5.
1 #异常值处理 2 print(df.describe())
6.
1 from sklearn.linear_model import LinearRegression 2 X = df.drop("标题",axis=1) 3 predict_model = LinearRegression() 4 predict_model.fit(X,df['热度数据']) 5 print("回归系数为:",predict_model.coef_)
7.
1 #绘制排名与热度的回归图 2 import seaborn as sns 3 sns.lmplot(x='排名', y='热度数据', data=df, ci=None)
8.
1 import numpy as np 2 #画出散点图 3 plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 4 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 5 N=100 6 x=np.random.rand(N) 7 y=np.random.rand(N) 8 size=50 9 plt.xlabel("排名") 10 plt.ylabel("热度数据") 11 plt.scatter(x,y,size,color='b',alpha=0.5,marker="o") 12 #散点图 13 sns.jointplot(x="排名",y="热度数据",data=df,kind='reg',color='g') 14 sns.jointplot(x="排名",y="热度数据",data=df,kind='hex',color='r') 15 sns.jointplot(x="排名",y="热度数据",data=df,kind="kde",space=0,color='bule')
9.
1 import csv 2 import matplotlib.pyplot as plt 3 import pandas as pd 4 xdata = [] 5 ydata = [] 6 xdata = df.loc[:,'排名'] #将csv中列名为“列名1”的列存入xdata数组中 7 #如果ix报错请将其改为loc 8 ydata = df.loc[:,'热度数据'] 9 plt.plot(xdata,ydata,'bo-',label=u'',linewidth=1) 10 plt.title(u"折线图",size=10) #设置表名为“表名” 11 plt.legend() 12 plt.xlabel(u'排名',size=10) #设置x轴名为“x轴名” 13 plt.ylabel(u'热度数据',size=10) #设置y轴名为“y轴名” 14 plt.show()
10.
1 #标题直方图分析趋势 2 import matplotlib.pyplot as plt 3 x = df['标题'].head(20) 4 y = df['热度数据'].head(20) 5 plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 6 plt.rcParams['axes.unicode_minus']=False 7 plt.xticks(rotation=90) 8 plt.bar(x,y,alpha=0.2, width=0.4, color='b', lw=3,label="标题") 9 plt.plot(x,y,'-',color = 'r',label="热度数据") 10 plt.legend(loc = "best")#图例 11 plt.title("热搜指数趋势图") 12 plt.xlabel("标题",)#横坐标名字 13 plt.ylabel("热度数据")#纵坐标名字 14 plt.show()
11.
1 #标题水平直方图 2 plt.barh(x,y, alpha=0.2, height=0.4, color='red',label="热度数据", lw=3) 3 plt.title("热搜指数水平图") 4 plt.legend(loc = "best")#图例 5 plt.xlabel("标题",)#横坐标名字 6 plt.ylabel("热度数据")#纵坐标名字 7 plt.show()
12.
1 #绘画盒图 2 plt.xlabel("排名") 3 plt.ylabel("热度数据") 4 sns.boxplot(x='排名',y='热度数据',data=df)
13.
1 #标题云图 2 import pandas as pd 3 import numpy as np 4 import wordcloud as wc 5 from PIL import Image 6 import matplotlib.pyplot as plt 7 import random 8 9 bk = np.array(Image.open(r"C:\Users\12278\Desktop\无标题.png")) 10 mask = bk 11 # 定义尺寸 12 word_cloud = wc.WordCloud( 13 width=2000, # 词云图宽 14 height=1000, # 词云图高 15 mask = mask, 16 background_color='black', # 词云图背景颜色,默认为白色 17 font_path='msyhbd.ttc', # 词云图 字体(中文需要设定为本机有的中文字体) 18 max_font_size=400, # 最大字体,默认为200 19 random_state=50, # 为每个单词返回一个PIL颜色 20 ) 21 text = df["标题"] 22 text = " ".join(text) 23 word_cloud.generate(text) 24 plt.imshow(word_cloud) 25 plt.show()
1 #数据持久化 2 df = pd.DataFrame(df,columns=["排名","热度数据","标题"]) 3 df.to_csv('百度3.csv',encoding = 'gbk') #保存文件,数据持久化
四.完整代码
1 #输入所要爬取的网页 2 url="https://top.baidu.com/board?tab=realtime" 3 #伪装爬虫头避免被检测拦截 4 headers = {'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'} 5 #请求网站 6 r=requests.get(url) 7 #print(r.text) 8 #对页面内容重新编码 9 r.encoding=r.apparent_encoding 10 data=r.text 11 #使用BeautifulSoup 12 soup=BeautifulSoup(data,'html.parser') 13 #显示网站结构 14 #print(soup.prettify()) 15 head=[] 16 index=[] 17 for i in soup.find_all(class_="hot-index_1Bl1a"): 18 head.append(i.get_text().strip()) 19 for i in soup.find_all(class_="c-single-text-ellipsis"): 20 index.append(i.get_text().strip()) 21 data=[head,index] 22 s=pd.DataFrame(data,index=["标题","热度数据"]) 23 #将所得数据进行可视化 24 print(s.T) 25 #将数据保存至本地并进行数据的清理 26 S="F:\各种工作杂碎东西\\baidu1.csv" 27 df=pd.DataFrame(data,index=["标题","热度数据"]) 28 df.T.to_csv(S,encoding="utf_8_sig") 29 30 #清洗数据 31 #有表头读入 32 df = pd.read_csv('F:\各种工作杂碎东西\\baidu1.csv') 33 #修改表头 34 df = pd.read_csv('F:\各种工作杂碎东西\\baidu1.csv',header=None,names=['排名','热度数据','标题']) 35 #调整排名 36 df=df.drop([0]) 37 for i in range(31): 38 df['排名'].loc[i] =i 39 #清洗数据 40 #有表头读入 41 df = pd.read_csv('F:\各种工作杂碎东西\\baidu1.csv') 42 #修改表头 43 df = pd.read_csv('F:\各种工作杂碎东西\\baidu1.csv',header=None,names=['排名','热度数据','标题']) 44 #调整排名 45 df=df.drop([0]) 46 for i in range(31): 47 df['排名'].loc[i] =i 48 #清洗数据 49 #有表头读入 50 df = pd.read_csv('F:\各种工作杂碎东西\\baidu1.csv') 51 #修改表头 52 df = pd.read_csv('F:\各种工作杂碎东西\\baidu1.csv',header=None,names=['排名','热度数据','标题']) 53 #调整排名 54 df=df.drop([0]) 55 for i in range(31): 56 df['排名'].loc[i] =i 57 #检查是否有重复值 58 print(df.duplicated()) 59 #检查是否有空值 60 print(df['热度数据'].isnull().value_counts()) 61 #异常值处理 62 print(df.describe()) 63 X = df.drop("标题",axis=1) 64 predict_model = LinearRegression() 65 predict_model.fit(X,df['热度数据']) 66 print("回归系数为:",predict_model.coef_) 67 sns.lmplot(x='排名', y='热度数据', data=df, ci=None) 68 #画出散点图 69 plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 70 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 71 N=100 72 x=np.random.rand(N) 73 y=np.random.rand(N) 74 size=50 75 plt.xlabel("排名") 76 plt.ylabel("热度数据") 77 plt.scatter(x,y,size,color='b',alpha=0.5,marker="o") 78 #散点图 79 sns.jointplot(x="排名",y="热度数据",data=df,kind='reg',color='g') 80 sns.jointplot(x="排名",y="热度数据",data=df,kind='hex',color='r') 81 sns.jointplot(x="排名",y="热度数据",data=df,kind="kde",space=0,color='bule') 82 xdata = [] 83 ydata = [] 84 xdata = df.loc[:,'排名'] #将csv中列名为“列名1”的列存入xdata数组中 85 #如果ix报错请将其改为loc 86 ydata = df.loc[:,'热度数据'] 87 plt.plot(xdata,ydata,'bo-',label=u'',linewidth=1) 88 plt.title(u"折线图",size=10) #设置表名为“表名” 89 plt.legend() 90 plt.xlabel(u'排名',size=10) #设置x轴名为“x轴名” 91 plt.ylabel(u'热度数据',size=10) #设置y轴名为“y轴名” 92 plt.show() 93 x = df['标题'].head(20) 94 y = df['热度数据'].head(20) 95 plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 96 plt.rcParams['axes.unicode_minus']=False 97 plt.xticks(rotation=90) 98 plt.bar(x,y,alpha=0.2, width=0.4, color='b', lw=3,label="标题") 99 plt.plot(x,y,'-',color = 'r',label="热度数据") 100 plt.legend(loc = "best")#图例 101 plt.title("热搜指数趋势图") 102 plt.xlabel("标题",)#横坐标名字 103 plt.ylabel("热度数据")#纵坐标名字 104 plt.show() 105 #标题水平直方图 106 plt.barh(x,y, alpha=0.2, height=0.4, color='red',label="热度数据", lw=3) 107 plt.title("热搜指数水平图") 108 plt.legend(loc = "best")#图例 109 plt.xlabel("标题",)#横坐标名字 110 plt.ylabel("热度数据")#纵坐标名字 111 plt.show() 112 #标题散点图 113 114 plt.scatter(x,y,color='b',marker='o',s=40,alpha=0.5) 115 plt.xticks(rotation=90) 116 plt.title("热搜指数散点图") 117 plt.xlabel("hot_title",)#横坐标名字 118 plt.ylabel("hot_zhishu")#纵坐标名字 119 plt.show() 120 bk = np.array(Image.open(r"C:\Users\12278\Desktop\无标题.png")) 121 mask = bk 122 # 定义尺寸 123 word_cloud = wc.WordCloud( 124 width=2000, # 词云图宽 125 height=1000, # 词云图高 126 mask = mask, 127 background_color='black', # 词云图背景颜色,默认为白色 128 font_path='msyhbd.ttc', # 词云图 字体(中文需要设定为本机有的中文字体) 129 max_font_size=400, # 最大字体,默认为200 130 random_state=50, # 为每个单词返回一个PIL颜色 131 ) 132 text = df["标题"] 133 text = " ".join(text) 134 word_cloud.generate(text) 135 plt.imshow(word_cloud) 136 plt.show() 137 #绘画盒图 138 plt.xlabel("排名") 139 plt.ylabel("热度数据") 140 sns.boxplot(x='排名',y='热度数据',data=df) 141 #数据持久化 142 df = pd.DataFrame(df,columns=["排名","热度数据","标题"]) 143 df.to_csv('百度3.csv',encoding = 'gbk') #保存文件,数据持久化
四.总结
1.通过对数据的分析可以发现整体的热度是成一次函数形式上升的,并且热度值最高点与最低点之间相差300W之间,普通热点第一一般不会超过500W,最低热点也有200W以上。
2.小结:在这次对百度热榜的分析的过程中,我从中学会了不少函数及用法。很多次都卡在一个点上,绞尽脑汁去想解决问题的办法,通过观看b站的视频,百度搜索等方法去找寻答案。这两个星期来也养成了耐心和独立思考的习惯,并且提高了我对Python的兴趣。