python | 豆瓣音樂排行榜數據爬取分析及可視化
一、選題背景
其實簡單的對信息的下載,我們用不到爬蟲出馬,簡單的一個單機下載,就可以解決下載的問題,但是對於想要多個音樂(排行榜里),有一定規律的音樂進行下載我們就可以看到Python給我們帶來的便利,其實也是一種對數據進行搜集的一種方式。希望通過簡單的音樂排名的爬取可以讓我們更加了解python,並且對音樂數據背后帶來的信息進行分析。對於音樂爬取,這個不涉及到版權的問題,爬取上應該沒有太多的限制,那我們要找的就是一個音樂排行榜進行爬取學習,分析。我這里找的是豆瓣音樂本周音樂人最熱單曲排行榜。我們確定我們想要的數據對應的排行了,這樣我們對於我們的目標就又近了一步。
二、設計方案
1、名稱
豆瓣音樂排行榜數據爬取分析及可視化
2.內容與數據特征分析
爬取歌曲播放量的數據,分析各類數據之間的特征與關系
3.設計方案概述
通過訪問網頁源代碼,爬取數據,分析html頁面,標記需要的數據標簽,對數據提取、處理、可視化、繪制圖形、保存數據。
三、主題頁面的結構特征分析
1、主題頁面的結構與特征分析
數據來源:https://music.douban.com/chart
從下方網站頁面截圖可看出,頁面結構大致分為三部分,我們需要爬取的數據基本在左下邊,其他的可以不去考慮。
2、Htmls頁面解析
3.節點(標簽)查找方法與遍歷方法(必要時畫出節點樹結構)
四、網絡爬蟲程序設計
1、數據爬取與采集
1 #-*- coding = utf-8 -*- 2 from bs4 import BeautifulSoup 3 #進行網頁解析 4 5 import re 6 #進行文字匹配 7 8 import urllib.request,urllib.error 9 #制定URL,獲取網頁數據 10 11 import xlwt 12 #進行excel操作 13 14 import sqlite3 15 #進行SQLite數據庫操作 16 17 18 #開始爬取數據 19 def getData(url): 20 datalist = [] 21 html = askURL(url) 22 soup = BeautifulSoup(html,"html.parser") 23 i=1 24 for item in soup.find_all('li', class_="clearfix"): 25 data = [] 26 item = str(item) 27 pm = i 28 i=i+1 29 data.append(pm) 30 findgm = re.compile(r'javascript:;">(.*?)</a>') 31 gm = re.findall(findgm, item)[0] 32 data.append(gm) 33 if i<=11: 34 findbfl = re.compile(r'\xa0/\xa0(.*?)</p>') 35 bfl = re.findall(findbfl, item)[0] 36 data.append(bfl) 37 else: 38 findbfl2 = re.compile(r'\xa0/\xa0(.*?)\n') 39 bfl2 = re.findall(findbfl2, item)[0] 40 data.append(bfl2) 41 datalist.append(data) 42 if i==16: 43 break 44 return datalist 45 46 47 48 def askURL(url): 49 head = { 50 "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" 51 } 52 request = urllib.request.Request(url, headers=head) 53 html = "" 54 try: 55 response = urllib.request.urlopen(request) 56 html = response.read().decode("utf-8") 57 except urllib.error.URLError as e: 58 if hasattr(e, "code"): 59 print(e.code) 60 61 if hasattr(e, "reason"): 62 print(e.reason) 63 64 return html 65 66 67 68 url = ("https://music.douban.com/chart") 69 html=askURL(url) 70 datalist = getData(url) 71 print(datalist) 72 savepath = ".\\豆瓣音樂本周音樂人最熱單曲排行榜.xls" 73 book = xlwt.Workbook(encoding="utf-8",style_compression=0) 74 75 #創建workbook對象 76 sheet = book.add_sheet('豆瓣音樂本周音樂人最熱單曲排行榜',cell_overwrite_ok=True) 77 78 #創建工作表 79 #列名 80 col = ("排名","歌名","播放量") 81 82 #創建表頭 83 for i in range(0,3): 84 sheet.write(0,i,col[i]) 85 86 #輸入數據 87 for i in range(0,15): 88 #將播放量數據轉化為純數字格式 89 datalist[i][2] = datalist[i][2].replace('次播放','') 90 data = datalist[i] 91 for j in range(0,3): 92 sheet.write(i+1,j,data[j]) 93 94 book.save(savepath) 95 96 print('已輸出表格!') 97 print("爬取完畢!")
2、讀取數據
1 import pandas as pd 2 3 #導入數據 4 df_gm = pd.read_excel("豆瓣音樂本周音樂人最熱單曲排行榜.xls",encoding='utf-8') 5 6 #顯示數據表格 7 df_gm.head(15)
輸出內容如下:
3、數據清洗和處理
(1)查看是否有重復行,有重復行返回True,沒有重復行返回False
1 df_gm.duplicated()
(2)判斷數據行中是否存在缺失值,有缺失值返回True,沒有缺失值返回False
1 df_gm.isnull().any(axis=1)
(3)查看是否有空值,有空值返回True,沒有空值返回False
1 df_gm.isnull()
(4)查看是否存在異常值
1 df_gm.describe()
4、數據分析與可視化
(1)散點折線圖
1 #繪制散點折線圖 2 import pandas as pd 3 import numpy as np 4 import matplotlib.pyplot as plt 5 df_gm = pd.read_excel("豆瓣音樂本周音樂人最熱單曲排行榜.xls") 6 7 #散點 8 plt.scatter(df_gm.排名,df_gm.播放量,color='b') 9 10 #折線 11 plt.plot(df_gm.排名,df_gm.播放量,color='r') 12 13 #添加x軸標簽和y軸標簽 14 plt.xlabel('PM') 15 plt.ylabel('BFL') 16 17 plt.show()
(2)數據柱形圖
1 #繪制數據柱形圖 2 import matplotlib.pyplot as plt 3 import pandas as pd 4 import numpy as np 5 6 kuake_df=pd.read_excel(r'C:\Users\20832\豆瓣音樂本周音樂人最熱單曲排行榜.xls') 7 data=np.array(kuake_df['播放量'][0:15]) 8 9 #添加x軸標簽和y軸標簽 10 plt.xlabel('PM') 11 plt.ylabel('BFL') 12 13 s = pd.Series(data, index) 14 s.plot(kind='bar',color='cyan') 15 16 #添加網格 17 plt.grid() 18 19 plt.show()
(3)線性回歸方程
1 #線性回歸方程 2 import pandas as pd 3 from sklearn import datasets 4 from sklearn.datasets import load_boston 5 from sklearn.linear_model import LinearRegression 6 df_gm=pd.read_excel(r'C:\Users\20832\豆瓣音樂本周音樂人最熱單曲排行榜.xls') 7 predict_model=LinearRegression() 8 X=df_gm[["排名"]] 9 Y=df_gm["播放量"] 10 predict_model.fit(X,Y) 11 np.set_printoptions(precision=3,suppress=True) 12 print("回歸方程系數為{}".format( predict_model.coef_)) 13 print("回歸方程截距:{0:2f}".format( predict_model.intercept_))
1 #繪制線性回歸方程圖 2 import matplotlib.pyplot as plt 3 import matplotlib 4 import numpy as np 5 import scipy.optimize as opt 6 df_gm=pd.read_excel(r'C:\Users\20832\豆瓣音樂本周音樂人最熱單曲排行榜.xls') 7 x0=np.array(df_gm['排名']) 8 y0=np.array(df_gm['播放量']) 9 def func(x,c0): 10 a,b,c=c0 11 return a*x**2+b*x+c 12 def errfc(c0,x,y): 13 return y-func(x,c0) 14 c0=[0,2,3] 15 c1=opt.leastsq(errfc,c0,args=(x0,y0))[0] 16 a,b,c=c1 17 print(f"擬合方程為:y={a}*x**2+{b}*x+{c}") 18 chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc') 19 plt.plot(x0,y0,"ob",label="樣本數據") 20 plt.plot(x0,func(x0,c1),"r",label="擬合曲線") 21 #添加x軸標簽和y軸標簽 22 plt.xlabel("PM") 23 plt.ylabel("BFL") 24 plt.legend(loc=3,prop=chinese) 25 plt.show()
5、完整代碼
1 #-*- coding = utf-8 -*- 2 from bs4 import BeautifulSoup 3 #進行網頁解析 4 5 import re 6 #進行文字匹配 7 8 import urllib.request,urllib.error 9 #制定URL,獲取網頁數據 10 11 import xlwt 12 #進行excel操作 13 14 import sqlite3 15 #進行SQLite數據庫操作 16 17 18 #開始爬取數據 19 def getData(url): 20 datalist = [] 21 html = askURL(url) 22 soup = BeautifulSoup(html,"html.parser") 23 i=1 24 for item in soup.find_all('li', class_="clearfix"): 25 data = [] 26 item = str(item) 27 pm = i 28 i=i+1 29 data.append(pm) 30 findgm = re.compile(r'javascript:;">(.*?)</a>') 31 gm = re.findall(findgm, item)[0] 32 data.append(gm) 33 if i<=11: 34 findbfl = re.compile(r'\xa0/\xa0(.*?)</p>') 35 bfl = re.findall(findbfl, item)[0] 36 data.append(bfl) 37 else: 38 findbfl2 = re.compile(r'\xa0/\xa0(.*?)\n') 39 bfl2 = re.findall(findbfl2, item)[0] 40 data.append(bfl2) 41 datalist.append(data) 42 if i==16: 43 break 44 return datalist 45 46 47 48 def askURL(url): 49 head = { 50 "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" 51 } 52 request = urllib.request.Request(url, headers=head) 53 html = "" 54 try: 55 response = urllib.request.urlopen(request) 56 html = response.read().decode("utf-8") 57 except urllib.error.URLError as e: 58 if hasattr(e, "code"): 59 print(e.code) 60 61 if hasattr(e, "reason"): 62 print(e.reason) 63 64 return html 65 66 67 68 url = ("https://music.douban.com/chart") 69 html=askURL(url) 70 datalist = getData(url) 71 print(datalist) 72 savepath = ".\\豆瓣音樂本周音樂人最熱單曲排行榜.xls" 73 book = xlwt.Workbook(encoding="utf-8",style_compression=0) 74 75 #創建workbook對象 76 sheet = book.add_sheet('豆瓣音樂本周音樂人最熱單曲排行榜',cell_overwrite_ok=True) 77 78 #創建工作表 79 #列名 80 col = ("排名","歌名","播放量") 81 82 #創建表頭 83 for i in range(0,3): 84 sheet.write(0,i,col[i]) 85 86 #輸入數據 87 for i in range(0,15): 88 #將播放量數據轉化為純數字格式 89 datalist[i][2] = datalist[i][2].replace('次播放','') 90 data = datalist[i] 91 for j in range(0,3): 92 sheet.write(i+1,j,data[j]) 93 94 book.save(savepath) 95 96 print('已輸出表格!') 97 98 print("爬取完畢!") 99 100 101 102 import pandas as pd 103 104 #導入數據 105 df_gm = pd.read_excel("豆瓣音樂本周音樂人最熱單曲排行榜.xls",encoding='utf-8') 106 107 #顯示數據表格 108 df_gm.head(15) 109 110 #查看是否有重復行,有重復行返回True,沒有重復行返回False 111 df_gm.duplicated() 112 113 #判斷數據行中書是否存在缺失值,有缺失值返回True,沒有缺失值返回False 114 df_gm.isnull().any(axis=1) 115 116 # 查看是否有空值,有空值返回True,沒有空值返回False 117 df_gm.isnull() 118 119 #查看是否存在異常值 120 df_gm.describe() 121 122 123 124 #繪制散點折線圖 125 import pandas as pd 126 import numpy as np 127 import matplotlib.pyplot as plt 128 129 df_gm = pd.read_excel("豆瓣音樂本周音樂人最熱單曲排行榜.xls") 130 131 #散點 132 plt.scatter(df_gm.排名,df_gm.播放量,color='b') 133 134 #折線 135 plt.plot(df_gm.排名,df_gm.播放量,color='r') 136 137 #添加x軸標簽和y軸標簽 138 plt.xlabel('PM') 139 plt.ylabel('BFL') 140 141 plt.show() 142 143 144 145 #繪制數據柱形圖 146 import pandas as pd 147 import numpy as np 148 import matplotlib.pyplot as plt 149 150 kuake_df=pd.read_excel(r'C:\Users\20832\豆瓣音樂本周音樂人最熱單曲排行榜.xls') 151 data=np.array(kuake_df['播放量'][0:15]) 152 153 #添加x軸標簽和y軸標簽 154 plt.xlabel('PM') 155 plt.ylabel('BFL') 156 157 s = pd.Series(data, index) 158 s.plot(kind='bar',color='cyan') 159 160 #添加網格 161 plt.grid() 162 163 plt.show() 164 165 166 167 #線性回歸方程 168 import pandas as pd 169 from sklearn import datasets 170 from sklearn.datasets import load_boston 171 from sklearn.linear_model import LinearRegression 172 173 df_gm=pd.read_excel(r'C:\Users\20832\豆瓣音樂本周音樂人最熱單曲排行榜.xls') 174 predict_model=LinearRegression() 175 176 #設定X和Y變量 177 X=df_gm[["排名"]] 178 Y=df_gm["播放量"] 179 predict_model.fit(X,Y) 180 np.set_printoptions(precision=3,suppress=True) 181 print("回歸方程系數為{}".format( predict_model.coef_)) 182 print("回歸方程截距:{0:2f}".format( predict_model.intercept_)) 183 184 185 186 #繪制線性回歸方程圖 187 import matplotlib.pyplot as plt 188 import matplotlib 189 import numpy as np 190 import scipy.optimize as opt 191 192 df_gm=pd.read_excel(r'C:\Users\20832\豆瓣音樂本周音樂人最熱單曲排行榜.xls') 193 194 x0=np.array(df_gm['排名']) 195 y0=np.array(df_gm['播放量']) 196 def func(x,c0): 197 a,b,c=c0 198 return a*x**2+b*x+c 199 def errfc(c0,x,y): 200 return y-func(x,c0) 201 202 c0=[0,2,3] 203 c1=opt.leastsq(errfc,c0,args=(x0,y0))[0] 204 a,b,c=c1 205 print(f"擬合方程為:y={a}*x**2+{b}*x+{c}") 206 207 chinese=matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc') 208 plt.plot(x0,y0,"ob",label="樣本數據") 209 plt.plot(x0,func(x0,c1),"r",label="擬合曲線") 210 211 #添加x軸標簽和y軸標簽 212 plt.xlabel("PM") 213 plt.ylabel("BFL") 214 215 plt.legend(loc=3,prop=chinese) 216 plt.show()
五、總結
1、一步步分析,在進行爬蟲爬取的時候要注意,有時候的參數是可以省略的,因此在構造請求信息的時候就可以省略參數的信息。
2、通過這次的期末設計項目學習,我深深的感覺到自己不論是知識層面上還是動手實踐能力上都很欠缺,學無止境。雖然本學期即將結束,但我們的學習永遠不會有終點。希望通過本次總結,我可以更好的認清自己的優缺點,取長補短,在今后的學習中不斷提升自己的能力!