實(shí)戰(zhàn)|手把手教你用Python爬取存儲(chǔ)數(shù)據(jù),還能自動(dòng)在Excel中可視化!
大家好,在之前我們講過如何用Python構(gòu)建一個(gè)帶有GUI的爬蟲小程序,很多本文將迎合熱點(diǎn),延續(xù)上次的NBA爬蟲GUI,探討如何爬取虎撲NBA官網(wǎng)數(shù)據(jù)。?并且將數(shù)據(jù)寫入Excel中同時(shí)自動(dòng)生成折線圖,主要有以下幾個(gè)步驟

本文將分為以下兩個(gè)部分進(jìn)行講解
在虎撲NBA官網(wǎng)球員頁面中進(jìn)行爬蟲,獲取球員數(shù)據(jù)。 清洗整理爬取的球員數(shù)據(jù),對(duì)其進(jìn)行可視化。
項(xiàng)目主要涉及的Python模塊:
requestspandasbs4
? 爬蟲部分
爬蟲部分整理思路如下?
觀察URL1的源代碼找到球隊(duì)名稱與對(duì)應(yīng)URL2觀察URL2的源代碼找到球員對(duì)應(yīng)的URL3觀察URL3源代碼找到對(duì)應(yīng)球員基本信息與比賽數(shù)據(jù)并進(jìn)行篩選存儲(chǔ)
其實(shí)爬蟲就是在html上操作,而html的結(jié)構(gòu)很簡單就只有一個(gè),就是一個(gè)大框討一個(gè)小框,小框在套小框,這樣的一層層嵌套。
目標(biāo)URL如下:
URL1: http://nba.hupu.com/players/URL2(此處以湖人球隊(duì)為例): https://nba.hupu.com/players/lakersURL3(此處以詹姆斯為例): https://nba.hupu.com/players/lebronjames-650.html
先引用模塊
from?bs4?import?BeautifulSoup
import?requests
import?xlsxwriter
import?os
查看URL1源代碼代碼,可以看到球隊(duì)名詞及其對(duì)應(yīng)的URL2在span標(biāo)簽中下,進(jìn)而找到它的父框與祖父框,下面的思路都是如此,圖如下:
此時(shí),可以通過requests模塊與bs4模塊進(jìn)行有目的性的索引,得到球隊(duì)的名稱列表。
def?Teamlists(url):
????TeamName=[]?
????TeamURL=[]?
????GET=requests.get(URL1)
????soup=BeautifulSoup(GET.content,'lxml')
????lables=soup.select('html?body?div?div?div?ul?li?span a')?
????for?lable?in?lables:
????????ballname=lable.get_text()
????????TeamName.append(ballname)
????????print(ballname)
????teamname=input("請(qǐng)輸入想查詢的球隊(duì)名:")#此處可變?yōu)镚UI界面中的按鍵值
????c=TeamName.index(teamname)
????for?item?in?lables:
?????HREF=item.get('href')
?????TeamURL.append(HREF)
????URL2=TeamURL[c]?
????return?URL2就此得到了對(duì)應(yīng)球隊(duì)的URL2,接著觀察URL2網(wǎng)頁的內(nèi)容,可以看到球員名稱在標(biāo)簽a中下,同時(shí)也存放著對(duì)應(yīng)球員的URL3,如下圖:
此時(shí),故依然通過requests模塊與bs4模塊進(jìn)行相對(duì)應(yīng)的索引,得到球員名稱列表以及對(duì)應(yīng)的URL3。
#自定義函數(shù)獲取隊(duì)員列表和對(duì)應(yīng)的URL
def?playerlists(URL2):
????PlayerName=[]?
????PlayerURL=[]?
????GET2=requests.get(URL1)
????soup2=BeautifulSoup(GET2.content,'lxml')
????lables2=soup2.select('html?body?div?div?table?tbody?tr?td?b?a')
????for?lable2?in?lables2:
????????playername=lable2.get_text()
????????PlayerName.append(playername)
????????print(playername)
????name=input("請(qǐng)輸入球員名:")?#此處可變?yōu)镚UI界面中的按鍵值
????d=PlayerName.index(name)
????for?item2?in?lables2:
?????HREF2=item2.get('href')
?????PlayerURL.append(HREF2)
????URL3=PlayerURL[d]
????return?URL3,name
現(xiàn)在就此得到了對(duì)應(yīng)球隊(duì)的URL3,接著觀察URL3網(wǎng)頁的內(nèi)容,可以看到球員基本信息在標(biāo)簽p下,球員常規(guī)賽生涯數(shù)據(jù)與季后賽生涯數(shù)據(jù)在標(biāo)簽td下,如下圖:
同樣,依然通過requests模塊與bs4模塊進(jìn)行相對(duì)應(yīng)的索引,得到球員基本信息與生涯數(shù)據(jù),而對(duì)于球員的常規(guī)賽與季候賽的生涯數(shù)據(jù)將進(jìn)行篩選與儲(chǔ)存,得到data列表。
def?Competition(URL3):
????data=[]
????GET3=requests.get(URL3)
????soup3=BeautifulSoup(GET3.content,'lxml')
????lables3=soup3.select('html?body?div?div?div?div?div?div?div?div?p')
????lables4=soup3.select('div?div?table?tbody?tr?td')
????for?lable3?in?lables3:
?????introduction=lable3.get_text()?
?????print(introduction)??#球員基本信息
????for?lable4?in?lables4:
????????competition=lable4.get_text()
????????data.append(competition)?
????for?i?in?range(len(data)):
????????if?data[i]=='職業(yè)生涯常規(guī)賽平均數(shù)據(jù)':
????????????a=data[i+31]
????????????a=data.index(a)
????del(data[:a])?
????for?x?in?range(len(data)):
????????if?data[x]=='職業(yè)生涯季后賽平均數(shù)據(jù)':
????????????b=data[x]
????????????b=data.index(b)
????del(data[b:])
????return?data
通過上述網(wǎng)絡(luò)爬蟲得到了以下的數(shù)據(jù),提供可視化數(shù)據(jù)的同時(shí)便于綁定之后的GUI界面按鍵事件:
獲取NBA中的所有球隊(duì)的標(biāo)準(zhǔn)名稱; 通過指定的一只球隊(duì)獲取球隊(duì)中所有球員的標(biāo)準(zhǔn)名稱; 通過指定的球員獲取到對(duì)應(yīng)的基本信息以及常規(guī)賽與季后賽數(shù)據(jù);
? 可視化部分
思路:創(chuàng)建文件夾 創(chuàng)建表格和折線圖
自定義函數(shù)創(chuàng)建表格,運(yùn)用os模塊進(jìn)行編寫,返回已創(chuàng)文件夾的路徑,代碼如下:
def?file_add(path):??#此時(shí)的內(nèi)函數(shù)path可與GUI界面的Statictext綁定
????creatpath=path+'\\Basketball'?
????try:
?????if?not?os.path.isdir(creatpath):
??????os.makedirs(creatpath)???????
????except:
?????print("文件夾存在")
????return?creatpath
運(yùn)用xlsxwriter模塊在creatpath路徑下自定義函數(shù)創(chuàng)建excel表格同時(shí)放入數(shù)據(jù)與構(gòu)造折線圖,代碼如下:
def?player_chart(name,data,creatpath):
????#此為表格名稱——球員名稱+chart
????EXCEL=xlsxwriter.Workbook(creatpath+'\\'+name+'chart.xlsx')
????worksheet=EXCEL.add_worksheet(name)?
????bold=EXCEL.add_format({'bold':1})?
????headings=data[:18]
????worksheet.write_row('A1',headings,bold)?#寫入表頭
????num=(len(data))//18
????a=0
????for?i?in?range(num):
????????a=a+18
????????c=a+18
????????i=i+1
????????worksheet.write_row('A'+str(i+1),data[a:c])?#寫入數(shù)據(jù)
????chart_col?=?EXCEL.add_chart({'type':?'line'})?#創(chuàng)建一個(gè)折線圖
????chart_col.add_series({
????????'name':?'='+name+'!$R$1',?#設(shè)置折線描述名稱
????????'categories':'='+name+'!$A$2:$A$'+str(num),?#設(shè)置圖表類別標(biāo)簽范圍
????????'values':?'='+name+'!$R$2:$R$'+str(num-1),????#設(shè)置圖表數(shù)據(jù)范圍
????????'line':?{'color':?'red'},?})???#設(shè)置圖表線條屬性
????#設(shè)置圖標(biāo)的標(biāo)題和想x,y軸信息
????chart_col.set_title({'name':?name+'生涯常規(guī)賽平均得分'})?
????chart_col.set_x_axis({'name':?'年份?(年)'})?
????chart_col.set_y_axis({'name':?'平均得分(分)'})
????chart_col.set_style(1)?#設(shè)置圖表風(fēng)格
????worksheet.insert_chart('A14',?chart_col,?{'x_offset':25,?'y_offset':3,})?#把圖標(biāo)插入工作臺(tái)中并設(shè)置偏移
????EXCEL.close()
數(shù)據(jù)表格效果展現(xiàn),以詹姆斯為例如下
并且此時(shí)打開自動(dòng)生成的Excel,對(duì)應(yīng)的折線圖就直接展現(xiàn)出來,無需再次整理!
現(xiàn)在結(jié)合任務(wù)一的網(wǎng)絡(luò)爬蟲與任務(wù)二的數(shù)據(jù)可視化,可以得到實(shí)時(shí)的球員常規(guī)賽數(shù)據(jù)與季后賽數(shù)據(jù)匯總,同時(shí)還有實(shí)時(shí)球員生涯折線圖。便可以與上次的GUI界面任務(wù)設(shè)計(jì)中的”可視化“按鈕事件綁定,感興趣的讀者可以自己進(jìn)一步研究!
-END-
PS:公號(hào)內(nèi)回復(fù)「Python」即可進(jìn)入Python 新手學(xué)習(xí)交流群,一起?100 天計(jì)劃!
老規(guī)矩,兄弟們還記得么,右下角的 “在看” 點(diǎn)一下,如果感覺文章內(nèi)容不錯(cuò)的話,記得分享朋友圈讓更多的人知道!


【神秘禮包獲取方式】
