Python爬虫进阶之爬取篮球赛数据
相信很多人都喜歡打籃球, 并且對(duì)自己喜歡的球星的比賽數(shù)據(jù)都很關(guān)注,于是我就想著去爬取籃球網(wǎng)站的數(shù)據(jù)。但是相對(duì)來(lái)說(shuō)爬取一個(gè)數(shù)據(jù)也沒(méi)啥挑戰(zhàn)性,于是我又趕著學(xué)習(xí)了xlsxwriter模塊,將爬取的的數(shù)據(jù)放入表格并制作折線圖。
第一步 robots協(xié)議
對(duì)于學(xué)習(xí)爬蟲(chóng)的小白來(lái)說(shuō)一定要注意robots協(xié)議,也稱為爬蟲(chóng)協(xié)議,機(jī)器人協(xié)議等,一般網(wǎng)站都會(huì)通過(guò)該協(xié)議告訴搜索引擎哪些頁(yè)面可以爬取或不可以爬取。
 首先我們?cè)谝廊【W(wǎng)站url后面加上robots.txt,
 
 雖然對(duì)于robots協(xié)議還不太懂,但大概知道我要爬取的內(nèi)容是可以的。
第二步 分析網(wǎng)站
可以看到,這就是一個(gè)單純的靜態(tài)網(wǎng)頁(yè),那要爬取東西就簡(jiǎn)單多了。
接著我們通過(guò)f12點(diǎn)擊頁(yè)面去查看源代碼,發(fā)現(xiàn)每個(gè)球隊(duì)的鏈接就嵌在代碼中
進(jìn)入球隊(duì)的網(wǎng)址后就可以看到每個(gè)球員的信息,并且球員的URL也嵌在代碼中。
 并且所有比賽數(shù)據(jù)和球員介紹也都在源代碼中獲得,無(wú)論是用Beautifulsoup,Xpath,還是正則表達(dá)式都可以輕松獲取。廢話少說(shuō)直接上代碼
第三步 寫(xiě)代碼
導(dǎo)入相關(guān)模塊
#coding=utf-8 from bs4 import BeautifulSoup import requests import xlsxwriter import os import re #留作備用,beautifulsoup我才看了半天不太熟悉定義函數(shù)獲取球隊(duì)列表和URL,果不其然,當(dāng)我用正則表達(dá)式的時(shí)候出現(xiàn)了嚴(yán)重的錯(cuò)誤,本來(lái)我是想通過(guò)輸入球隊(duì)名字用作參數(shù)放進(jìn)正則表達(dá)式中,應(yīng)為我想匹配的字符前面的都是a href=,也就是當(dāng)從頭到尾匹配的時(shí)候,他只從第一個(gè)開(kāi)始把符合的字符串返回給我,我實(shí)在沒(méi)想到辦法解決(我的正則表達(dá)式也沒(méi)學(xué)好),最后想到了用列表的方式將URL給匹配出來(lái)。
#自定義函數(shù)獲取球隊(duì)列表和相應(yīng)的URL def teamlists(url):name_list=[] #定義空列表放入所有球隊(duì)名稱teamurl_list=[] #定義空列表放入所有球隊(duì)對(duì)應(yīng)的URLhtml=requests.get(url)soup=BeautifulSoup(html.content,'lxml')#找到特定標(biāo)簽的元素links=soup.select('html body div div div ul li span a')for link in links:baskname=link.get_text()name_list.append(baskname)print(baskname)teamname=input("請(qǐng)輸入想查詢的球隊(duì)名:")c=name_list.index(teamname)for item in links:url1=item.get('href')teamurl_list.append(url1)TeamUrl=teamurl_list[c] # Team_pat=r'a href="(.*?)">'+teamname+'</a>,' # Team_url=re.findall(Team_pat,str(links)) # TeamUrl="".join(Team_url)return TeamUrl這個(gè)函數(shù)也是廢了很大的勁,剛開(kāi)始是沒(méi)有后面那兩個(gè)for循環(huán)的,因?yàn)槲倚枰臄?shù)據(jù)只是每個(gè)球員的職業(yè)生涯常規(guī)賽,當(dāng)我寫(xiě)完代碼運(yùn)行的時(shí)候發(fā)現(xiàn)獲取的數(shù)據(jù)都有偏差,只能準(zhǔn)確獲得哈登的數(shù)據(jù)(因?yàn)槲覄傞_(kāi)始一直照著哈登的數(shù)據(jù)堆代碼),后來(lái)才發(fā)現(xiàn)每個(gè)球員比賽的年份不一樣,于是乎才用了兩個(gè)for循環(huán)來(lái)刪掉指定的數(shù)據(jù)。
#自定義函數(shù)獲取指定隊(duì)員的比賽信息 def Competition(playersUrl):data=[]html3=requests.get(playersUrl)soup3=BeautifulSoup(html3.content,'lxml')links3=soup3.select('html body div div div div div div div div p')links4=soup3.select('div div table tbody tr td')for link3 in links3:introduction=link3.get_text() #輸入球員的名稱后返回球員的介紹print(introduction)for link4 in links4:match_one=link4.get_text()data.append(match_one) #將比賽的數(shù)據(jù)放入data # print(data)for i in range(len(data)):if data[i]=='職業(yè)生涯常規(guī)賽平均數(shù)據(jù)': # print(data.index('職業(yè)生涯常規(guī)賽平均數(shù)據(jù)'))a=data[i+31]a=data.index(a)del(data[:a]) #清除a之前的所有數(shù)據(jù)for x in range(len(data)):if data[x]=='職業(yè)生涯季后賽平均數(shù)據(jù)': # print(data.index('職業(yè)生涯季后賽平均數(shù)據(jù)'))b=data[x]b=data.index(b) # del(data[b:])del(data[b:]) #清除b之后的所有數(shù)據(jù)return data這個(gè)函數(shù)簡(jiǎn)直是絞盡腦汁,剛開(kāi)始寫(xiě)入數(shù)據(jù)我是一個(gè)一個(gè)寫(xiě)的,后來(lái)又發(fā)現(xiàn)每個(gè)人的數(shù)據(jù)都錯(cuò)位(原諒我又是照著哈登來(lái)寫(xiě)的),昨天想了一個(gè)下午才利用這個(gè)for循環(huán)來(lái)建立表格的數(shù)據(jù)。(太喜歡用for循環(huán),萬(wàn)能,對(duì)于我們這種小白來(lái)說(shuō))。
#自定義函數(shù)創(chuàng)建表格和表圖 def player_chart(name,data,cur_path):workbook=xlsxwriter.Workbook(cur_path+'\\'+name+'chart.xlsx') #在指定路徑創(chuàng)建表格文件worksheet=workbook.add_worksheet(name) #創(chuàng)建工作臺(tái)bold=workbook.add_format({'bold':1}) #自定義樣式,加粗headings=data[:18]worksheet.write_row('A1',headings,bold) #寫(xiě)入表頭num=(len(data))//18a=0for i in range(num):a=a+18c=a+18i=i+1worksheet.write_row('A'+str(i+1),data[a:c]) #寫(xiě)入數(shù)據(jù)chart_col = workbook.add_chart({'type': 'line'}) #創(chuàng)建一個(gè)折線圖#配置第一個(gè)系列數(shù)據(jù) 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è)置偏移workbook.close()以上都是幾個(gè)比較重要的結(jié)構(gòu),我直接上源代碼
#coding=utf-8 from bs4 import BeautifulSoup import requests import xlsxwriter import os import re#自定義函數(shù)獲取球隊(duì)列表和相應(yīng)的URL def teamlists(url):name_list=[] #定義空列表放入所有球隊(duì)名稱teamurl_list=[] #定義空列表放入所有球隊(duì)對(duì)應(yīng)的URLhtml=requests.get(url)soup=BeautifulSoup(html.content,'lxml')links=soup.select('html body div div div ul li span a') #找到特定標(biāo)簽的元素for link in links:baskname=link.get_text()name_list.append(baskname)print(baskname)teamname=input("請(qǐng)輸入想查詢的球隊(duì)名:")c=name_list.index(teamname)for item in links:url1=item.get('href')teamurl_list.append(url1)TeamUrl=teamurl_list[c] # Team_pat=r'a href="(.*?)">'+teamname+'</a>,' # Team_url=re.findall(Team_pat,str(links)) # TeamUrl="".join(Team_url)return TeamUrl#自定義函數(shù)獲取隊(duì)員列表和對(duì)應(yīng)的URL def playerlists(TeamUrl):playname_list=[] #定義空列表放入所有球員名稱playurl_list=[] #定義空列表放入所有球員對(duì)應(yīng)的URLhtml2=requests.get(TeamUrl)soup2=BeautifulSoup(html2.content,'lxml')links2=soup2.select('html body div div table tbody tr td b a')for link2 in links2:playername=link2.get_text()playname_list.append(playername)print(playername)name=input("請(qǐng)輸入球員名:")d=playname_list.index(name)for item2 in links2:url2=item2.get('href')playurl_list.append(url2)playersUrl=playurl_list[d] # players_pat=r'a href="(.*?)" target="_blank">'+name # players_url=re.findall(players_pat,str(links2)) # playersUrl="".join(players_url)return playersUrl,name#自定義函數(shù)獲取指定隊(duì)員的比賽信息 def Competition(playersUrl):data=[]html3=requests.get(playersUrl)soup3=BeautifulSoup(html3.content,'lxml')links3=soup3.select('html body div div div div div div div div p')links4=soup3.select('div div table tbody tr td')for link3 in links3:introduction=link3.get_text() #輸入球員的名稱后返回球員的介紹print(introduction)for link4 in links4:match_one=link4.get_text()data.append(match_one) #將比賽的數(shù)據(jù)放入data # print(data)for i in range(len(data)):if data[i]=='職業(yè)生涯常規(guī)賽平均數(shù)據(jù)': # print(data.index('職業(yè)生涯常規(guī)賽平均數(shù)據(jù)'))a=data[i+31]a=data.index(a)del(data[:a]) #清除a之前的所有數(shù)據(jù)for x in range(len(data)):if data[x]=='職業(yè)生涯季后賽平均數(shù)據(jù)': # print(data.index('職業(yè)生涯季后賽平均數(shù)據(jù)'))b=data[x]b=data.index(b) # del(data[b:])del(data[b:]) #清除b之后的所有數(shù)據(jù)return data#自定義函數(shù)創(chuàng)建文件夾 def file_add(path):cur_path=path+'\\Basketball' #在指定路徑建立文件夾try:if not os.path.isdir(cur_path):#確認(rèn)文件夾是否存在os.makedirs(cur_path) #不存在則新建except:print("文件夾存在")return cur_path #自定義函數(shù)創(chuàng)建表格和表圖 def player_chart(name,data,cur_path):workbook=xlsxwriter.Workbook(cur_path+'\\'+name+'chart.xlsx') #在指定路徑創(chuàng)建表格文件worksheet=workbook.add_worksheet(name) #創(chuàng)建工作臺(tái)bold=workbook.add_format({'bold':1}) #自定義樣式,加粗headings=data[:18]worksheet.write_row('A1',headings,bold) #寫(xiě)入表頭num=(len(data))//18a=0for i in range(num):a=a+18c=a+18i=i+1worksheet.write_row('A'+str(i+1),data[a:c]) #寫(xiě)入數(shù)據(jù)chart_col = workbook.add_chart({'type': 'line'}) #創(chuàng)建一個(gè)折線圖#配置第一個(gè)系列數(shù)據(jù) 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è)置偏移workbook.close()if __name__ == '__main__':url="http://nba.hupu.com/players/"path='E:'TeamUrl=teamlists(url)playersUrl,name=playerlists(TeamUrl)data=Competition(playersUrl)cur_path=file_add(path)player_chart(name,data,cur_path)效果展示:
 
第四步 總結(jié)問(wèn)題
大家可以看到,對(duì)于beautifulsoup和正則表達(dá)式我不太熟悉,所以跟我一樣的小白一定要利用空閑時(shí)間多看看,但也告訴我們代碼是死的人是活的,要多利用其它的辦法去解決眼前的問(wèn)題,唯一一項(xiàng)我沒(méi)有解決成功的問(wèn)題就是我導(dǎo)入的折線圖沒(méi)辦法顯示出X軸的數(shù)據(jù),我試過(guò)很多次,看了很多博客都沒(méi)找到解決辦法,也有可能是Xlsxwriter不夠熟,留給評(píng)論區(qū)的大神幫我解決。最后還是希望大家好好學(xué)習(xí)天天向上。
xlsxwriter模塊參考文獻(xiàn):
 python寫(xiě)入excel(xlswriter)–生成圖表
總結(jié)
以上是生活随笔為你收集整理的Python爬虫进阶之爬取篮球赛数据的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: gnuplot绘图程序中对线型(line
- 下一篇: 网页拉取微信授权
