一、選題的背景
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這門課程研究的動力。最后,我希望通過此次經歷,會使我在以后的學習中,更加努力的提高自己的能力,掌握更深的知識。