一、选题的背景
QQ音乐是隶属于腾讯音乐娱乐集团的音乐流媒体平台。自2005年创立,QQ音乐注册用户总量已达8亿。QQ音乐以优质内容为核心,以大数据与互联网技术为推动力 ,致力于打造“智慧声态”的“立体”泛音乐生态圈,为用户提供多元化的音乐生活体验。通过对qq音乐热播榜的爬取与数据可视化分析,能够更好了解当代青年所关注的社会热点,了解当代青年的情感寄托等。
二、主题式网络爬虫设计方案
1.主题式网络爬虫名称:爬取qq音乐热播榜数据并数据分析及可视化
2.主题式网络爬虫爬取的内容与数据特征分析:
3.主题式网络爬虫设计方案概述:
实现思路:登录qq音乐,进入qq音乐热播榜,进入网页开发人员工具,得到网页源代码,查找所需标签的代码,进行数据采集,完成后对数据进行相应的分析整理并存入文档中。读取文件进行数据清洗和数据可视化,绘制图形进行数据分析。接下来分析排行和时长的数据拟合分析,最后进行数据持久化。
技术难点:爬取信息时对标签的寻找,回归方程运用得不够熟练等。
三、主题页面的结构特征分析
1.主题页面的结构与特征分析
通过对页面结构的分析,发现<div class="main">元素中,发现所需要的数据。并进行查找,在标签<class="songlist_number">,<class="songlist_time">,<class="playlist_author">,<a>分别找到排名,时长,作者,歌名的数据。
url为https://y.qq.com/n/ryqq/toplist/26
网址首页
2.Htmls 页面解析
通过查找网页源代码,浏览其中元素,并对其中元素进行解析


1.数据爬取与采集
#网页的爬取
1 #导入相关库 2 import requests 3 #引入pandas用于数据可视化 4 import pandas as pd 5 import numpy as np 6 import matplotlib.pyplot as plt 7 import matplotlib 8 import csv 9 import scipy as sp 10 import seaborn as sns 11 from sklearn.linear_model import LinearRegression 12 from bs4 import BeautifulSoup 13 from pandas import DataFrame 14 from scipy.optimize import leastsq 15 #搜索网址 16 url='https://y.qq.com/n/ryqq/toplist/26' 17 #伪装爬虫 18 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'} 19 20 r = requests.get(url, headers=headers,timeout=10) 21 22 def getHTMLText(url,timeout = 30): 23 try: 24 #用requests抓取网页信息 25 r = requests.get(url, timeout = 30) 26 #可以让程序产生异常时停止程序 27 r.raise_for_status() 28 #设置编码标准 29 r.encoding = r.apparent_encoding 30 return r.text 31 except: 32 return '产生异常' 33 34 35 #统一编码 36 html=r.text 37 #html.parser表示用BeautifulSoup库解析网页 38 soup=BeautifulSoup(html,'html.parser') 39 #基于bs4库HTML的格式输出,让页面更友好的显示 40 print(soup.prettify())
1 #爬取数据 2 #爬取排行 3 rank=[] 4 for m in soup.find_all(class_="songlist__number"): 5 rank.append(m.get_text().strip()) 6 print(rank) 7 8 #爬取时长 9 time=[] 10 for n in soup.find_all(class_="songlist__time"): 11 time.append(n.get_text().strip()) 12 13 print(time) 14 15 #爬取歌曲名 16 song=[] 17 for n in soup.find_all("a",class_=""): 18 song.append(n.get_text().strip()) 19 print(song) 20 21 #爬取作者 22 name=[] 23 for n in soup.find_all(class_="playlist__author"): 24 name.append(n.get_text().strip()) 25 print(name)
1 #将数据整理成表格 2 num=20 3 lst = [] 4 print('{:^5}\t{:^40}\t{:^10}\t{:^20}'.format('排名','时长','作者','歌名')) 5 for i in range(num): 6 7 print('{:^5}\t{:^40}\t{:^10}\t{:^20}'.format(i+1, time[i], name[i], song[i])) 8 lst.append([i+1, time[i], name[i], song[i]]) 9 df = pd.DataFrame(lst,columns=['排名','时长','作者','歌名']) 10 11 #将数据存入excel表 12 A = r'song.xlsx' 13 df.to_excel(A)
1 #读取excel表 2 df=pd.DataFrame(pd.read_excel('song.xlsx')) 3 print(df)
1 #数据清洗及处理 2 print('\n====各列是否有空值情况如下:====') 3 df.isnull() 4 df.isna().head()
1 print('\n====各列是否有重复值情况如下:====') 2 print(df.duplicated())
1 #数据汇总 2 print(df.describe()) 3 # 查找异常值 4 df.describe()
1 #数据分析 2 #数据可视化 3 import seaborn as sns 4 plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 5 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 6 sns.set(style='white') 7 plt.grid() 8 sns.regplot(df.排名,df.时长)
1 #画出散点图 2 # 用来正常显示中文标签 3 plt.rcParams['font.sans-serif'] = ['SimHei'] 4 # 用来正常显示负号 5 plt.rcParams['axes.unicode_minus'] = False 6 N=20 7 x=np.random.rand(N) 8 y=np.random.rand(N) 9 size=50 10 plt.grid() 11 plt.xlabel("排名") 12 plt.ylabel("热度") 13 plt.scatter(x,y,size,color='r',alpha=0.5,marker="o") 14 #散点图 kind='reg' 15 sns.jointplot(x="排名",y="时长",data=df,kind='reg') 16 # kind='hex' 17 sns.jointplot(x="排名",y="时长",data=df,kind='hex') 18 # kind='kde' 19 sns.jointplot(x="排名",y="时长",data=df,kind="kde")
1 import requests 2 from bs4 import BeautifulSoup 3 import bs4 4 #引入pandas用于数据可视化 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 #绘制 13 plt.rcParams['font.sans-serif']=['SimHei'] 14 a = df.排名 15 b = df.时长 16 plt.bar(a,b, color='b',label='时长') 17 plt.xlabel("排名") 18 plt.ylabel("时长") 19 plt.title('排名与时长数据柱状图') 20 plt.legend(loc=1) 21 plt.grid() 22 plt.show()
1 #绘制盒图 2 import seaborn as sns 3 def box(): 4 plt.title('时长指数盒图') 5 a = df.排名 6 b = df.时长 7 sns.boxplot(a,b) 8 plt.xlabel("排名") 9 plt.ylabel("时长") 10 11 box()
1 #绘制折线图 2 plt.rcParams['font.sans-serif']=['SimHei'] 3 a = df.排名 4 b = df.时长 5 plt.plot(a,b, color='r',label='时长') 6 plt.xlabel("排名") 7 plt.ylabel("时长") 8 plt.title('排名与时长数据折线图') 9 plt.legend(loc=1) 10 plt.grid() 11 plt.show()
1 #绘制直方图 2 plt.figure(dpi=100) 3 a = df.排名 4 b = df.时长 5 plt.bar(a,b,color='y') 6 plt.title("排名与时长数据直方图") 7 plt.xlabel("排名") 8 plt.ylabel("时长") 9 plt.grid() 10 plt.show()
1 #构建数据分析模型 2 import numpy as np 3 import pandas as pd 4 import sklearn 5 from sklearn import datasets 6 from sklearn.linear_model import LinearRegression 7 X = df[["排名"]] 8 predict_model = LinearRegression() 9 predict_model.fit(X, df[['时长']]) 10 11 print("回归系数为{}".format(predict_model.coef_)) 12 print("回归方程截距:{}".format(predict_model.intercept_))
1 #选择排名和热度两个特征变量,绘制分布图,用最小二乘法分析两个变量间的二次拟合方程和拟合曲线 2 colnames=[" ","排名","时长","作者","歌名"] 3 df = pd.read_excel('song.xlsx',skiprows=1,names=colnames) 4 X = df.排名 5 Y = df.时长 6 Z = df.作者 7 P = df.歌名 8 def A(): 9 plt.scatter(X,Y,color="blue",linewidth=2) 10 plt.title("分析图",color="blue") 11 plt.grid() 12 plt.show() 13 def B(): 14 plt.scatter(X,Y,color="green",linewidth=2) 15 plt.title("分析图",color="blue") 16 plt.grid() 17 plt.show() 18 def func(p,x): 19 a,b,c=p 20 return a*x*x+b*x+c 21 def error(p,x,y): 22 return func(p,x)-y 23 def main(): 24 plt.figure(figsize=(10,6)) 25 p0=[0,0,0] 26 Para = leastsq(error,p0,args=(X,Y)) 27 a,b,c=Para[0] 28 print("a=",a,"b=",b,"c=",c) 29 plt.scatter(X,Y,color="blue",linewidth=2) 30 x=np.linspace(0,20,20) 31 y=a*x*x+b*x+c 32 plt.plot(x,y,color="blue",linewidth=2,) 33 plt.title("分析图") 34 plt.grid() 35 plt.show() 36 print(A()) 37 print(B()) 38 print(main())
1 #数据持久化 2 A = r'song.xlsx' 3 df.to_excel(A)
1 #导入相关库 2 import requests 3 #引入pandas用于数据可视化 4 import pandas as pd 5 import numpy as np 6 import matplotlib.pyplot as plt 7 import matplotlib 8 import csv 9 import scipy as sp 10 import seaborn as sns 11 from sklearn.linear_model import LinearRegression 12 from bs4 import BeautifulSoup 13 from pandas import DataFrame 14 from scipy.optimize import leastsq 15 #搜索网址 16 url='https://y.qq.com/n/ryqq/toplist/26' 17 #伪装爬虫 18 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'} 19 20 r = requests.get(url, headers=headers,timeout=10) 21 22 def getHTMLText(url,timeout = 30): 23 try: 24 #用requests抓取网页信息 25 r = requests.get(url, timeout = 30) 26 #可以让程序产生异常时停止程序 27 r.raise_for_status() 28 #设置编码标准 29 r.encoding = r.apparent_encoding 30 return r.text 31 except: 32 return '产生异常' 33 34 35 #统一编码 36 html=r.text 37 #html.parser表示用BeautifulSoup库解析网页 38 soup=BeautifulSoup(html,'html.parser') 39 #基于bs4库HTML的格式输出,让页面更友好的显示 40 print(soup.prettify()) 41 42 #爬取数据 43 #爬取排行 44 rank=[] 45 for m in soup.find_all(class_="songlist__number"): 46 rank.append(m.get_text().strip()) 47 print(rank) 48 49 #爬取时长 50 time=[] 51 for n in soup.find_all(class_="songlist__time"): 52 time.append(n.get_text().strip()) 53 54 print(time) 55 56 #爬取歌曲名 57 song=[] 58 for n in soup.find_all("a",class_=""): 59 song.append(n.get_text().strip()) 60 print(song) 61 62 #爬取作者 63 name=[] 64 for n in soup.find_all(class_="playlist__author"): 65 name.append(n.get_text().strip()) 66 print(name) 67 68 #将数据整理成表格 69 num=20 70 lst = [] 71 print('{:^5}\t{:^40}\t{:^10}\t{:^20}'.format('排名','时长','作者','歌名')) 72 for i in range(num): 73 74 print('{:^5}\t{:^40}\t{:^10}\t{:^20}'.format(i+1, time[i], name[i], song[i])) 75 lst.append([i+1, time[i], name[i], song[i]]) 76 df = pd.DataFrame(lst,columns=['排名','时长','作者','歌名']) 77 78 #将数据存入excel表 79 A = r'song.xlsx' 80 df.to_excel(A) 81 82 #读取excel表 83 df=pd.DataFrame(pd.read_excel('song.xlsx')) 84 df 85 86 #数据清洗及处理 87 print('\n====各列是否有空值情况如下:====') 88 df.isnull() 89 df.isna().head() 90 print('\n====各列是否有重复值情况如下:====') 91 print(df.duplicated()) 92 # 查找异常值 93 df.describe() 94 #数据汇总 95 print(df.describe()) 96 97 #数据分析 98 #数据可视化 99 import seaborn as sns 100 plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 101 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 102 sns.set(style='white') 103 plt.grid() 104 sns.regplot(df.排名,df.时长) 105 #画出散点图 106 # 用来正常显示中文标签 107 plt.rcParams['font.sans-serif'] = ['SimHei'] 108 # 用来正常显示负号 109 plt.rcParams['axes.unicode_minus'] = False 110 N=20 111 x=np.random.rand(N) 112 y=np.random.rand(N) 113 size=50 114 plt.grid() 115 plt.xlabel("排名") 116 plt.ylabel("热度") 117 plt.scatter(x,y,size,color='r',alpha=0.5,marker="o") 118 #散点图 kind='reg' 119 sns.jointplot(x="排名",y="时长",data=df,kind='reg') 120 # kind='hex' 121 sns.jointplot(x="排名",y="时长",data=df,kind='hex') 122 # kind='kde' 123 sns.jointplot(x="排名",y="时长",data=df,kind="kde") 124 125 import requests 126 from bs4 import BeautifulSoup 127 import bs4 128 #引入pandas用于数据可视化 129 import pandas as pd 130 from pandas import DataFrame 131 import seaborn as sns 132 import numpy as np 133 import matplotlib.pyplot as plt 134 from scipy.optimize import leastsq 135 from sklearn.linear_model import LinearRegression 136 #绘制 137 plt.rcParams['font.sans-serif']=['SimHei'] 138 a = df.排名 139 b = df.时长 140 plt.bar(a,b, color='b',label='时长') 141 plt.xlabel("排名") 142 plt.ylabel("时长") 143 plt.title('排名与时长数据柱状图') 144 plt.legend(loc=1) 145 plt.grid() 146 plt.show() 147 148 #绘制盒图 149 import seaborn as sns 150 def box(): 151 plt.title('热度指数盒图') 152 a = df.排名 153 b = df.时长 154 sns.boxplot(a,b) 155 plt.xlabel("排名") 156 plt.ylabel("时长") 157 158 box() 159 160 #绘制折线图 161 plt.rcParams['font.sans-serif']=['SimHei'] 162 a = df.排名 163 b = df.时长 164 plt.plot(a,b, color='r',label='时长') 165 plt.xlabel("排名") 166 plt.ylabel("时长") 167 plt.title('排名与时长数据折线图') 168 plt.legend(loc=1) 169 plt.grid() 170 plt.show() 171 172 #构建数据分析模型 173 import numpy as np 174 import pandas as pd 175 import sklearn 176 from sklearn import datasets 177 from sklearn.linear_model import LinearRegression 178 X = df[["排名"]] 179 predict_model = LinearRegression() 180 predict_model.fit(X, df[['时长']]) 181 182 print("回归系数为{}".format(predict_model.coef_)) 183 print("回归方程截距:{}".format(predict_model.intercept_)) 184 185 #选择排名和热度两个特征变量,绘制分布图,用最小二乘法分析两个变量间的二次拟合方程和拟合曲线 186 colnames=[" ","排名","时长","作者","歌名"] 187 df = pd.read_excel('song.xlsx',skiprows=1,names=colnames) 188 X = df.排名 189 Y = df.时长 190 Z = df.作者 191 P = df.歌名 192 def A(): 193 plt.scatter(X,Y,color="blue",linewidth=2) 194 plt.title("分析图",color="blue") 195 plt.grid() 196 plt.show() 197 def B(): 198 plt.scatter(X,Y,color="green",linewidth=2) 199 plt.title("分析图",color="blue") 200 plt.grid() 201 plt.show() 202 def func(p,x): 203 a,b,c=p 204 return a*x*x+b*x+c 205 def error(p,x,y): 206 return func(p,x)-y 207 def main(): 208 plt.figure(figsize=(10,6)) 209 p0=[0,0,0] 210 Para = leastsq(error,p0,args=(X,Y)) 211 a,b,c=Para[0] 212 print("a=",a,"b=",b,"c=",c) 213 plt.scatter(X,Y,color="blue",linewidth=2) 214 x=np.linspace(0,20,20) 215 y=a*x*x+b*x+c 216 plt.plot(x,y,color="blue",linewidth=2,) 217 plt.title("分析图") 218 plt.grid() 219 plt.show() 220 print(A()) 221 print(B()) 222 print(main()) 223 224 #数据持久化 225 A = r'song.xlsx' 226 df.to_excel(A)
2.在完成此设计过程中,得到哪些收获?以及要改进的建议?
在完成此次设计的途中可谓是九九八十一难,无论是网站爬取,图表制作还是数据分析,都出现过大大小小的问题。例如在寻找要爬取的网站时,曾因为无法找到相关信息,出现乱码等,不得不反反复复更换十来个网站进行爬取。在绘制图表的过程中,也因为饼状图,堆叠图,3d散点图等图表制作的不熟练导致频频失误,最后只好放弃,改用其他图表。但在此次设计的重重“劫难”中也让我学到了许多知识。首先,为了这次设计,我不得不求学于我的课本以及之前上的网课,回忆重温之前的教学内容,除了令我对老师深厚的教学水准深感敬佩外,还巩固了我的课内知识。其次,在遇到课本也解决不了的问题的时候,我学会了去利用同学 与网络渠道去解决疑惑。这既锻炼了我的交流能力,同时也让我学习了颇多的课外知识,真是令我受益匪浅啊。此次作业,或许有很多不足,但是,这也令我意识到了自己的水平是多么的有限,对python这一门课程的理解是多么的有限。但是,这些不足也激起了我对python这门课程研究的动力。最后,我希望通过此次经历,会使我在以后的学习中,更加努力的提高自己的能力,掌握更深的知识。