Python爬虫进阶之爬取篮球赛数据

相信很多人都喜欢打篮球, 并且对自己喜欢的球星的比赛数据都很关注,于是我就想着去爬取篮球网站的数据。但是相对来说爬取一个数据也没啥挑战性,于是我又赶着学习了xlsxwriter模块,将爬取的的数据放入表格并制作折线图。

第一步 robots协议

对于学习爬虫的小白来说一定要注意robots协议,也称为爬虫协议,机器人协议等,一般网站都会通过该协议告诉搜索引擎哪些页面可以爬取或不可以爬取。
首先我们在要爬取网站url后面加上robots.txt,
在这里插入图片描述
虽然对于robots协议还不太懂,但大概知道我要爬取的内容是可以的。

第二步 分析网站

可以看到,这就是一个单纯的静态网页,那要爬取东西就简单多了。在这里插入图片描述

接着我们通过f12点击页面去查看源代码,发现每个球队的链接就嵌在代码中在这里插入图片描述

进入球队的网址后就可以看到每个球员的信息,并且球员的URL也嵌在代码中。在这里插入图片描述
并且所有比赛数据和球员介绍也都在源代码中获得,无论是用Beautifulsoup,Xpath,还是正则表达式都可以轻松获取。废话少说直接上代码

第三步 写代码

导入相关模块

#coding=utf-8
from bs4 import BeautifulSoup
import requests
import xlsxwriter
import os
import re #留作备用,beautifulsoup我才看了半天不太熟悉

定义函数获取球队列表和URL,果不其然,当我用正则表达式的时候出现了严重的错误,本来我是想通过输入球队名字用作参数放进正则表达式中,应为我想匹配的字符前面的都是a href=,也就是当从头到尾匹配的时候,他只从第一个开始把符合的字符串返回给我,我实在没想到办法解决(我的正则表达式也没学好),最后想到了用列表的方式将URL给匹配出来。

#自定义函数获取球队列表和相应的URL
def teamlists(url):
    name_list=[] #定义空列表放入所有球队名称
    teamurl_list=[] #定义空列表放入所有球队对应的URL
    html=requests.get(url)
    soup=BeautifulSoup(html.content,'lxml')
     #找到特定标签的元素
    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("请输入想查询的球队名:")
    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

这个函数也是废了很大的劲,刚开始是没有后面那两个for循环的,因为我需要的数据只是每个球员的职业生涯常规赛,当我写完代码运行的时候发现获取的数据都有偏差,只能准确获得哈登的数据(因为我刚开始一直照着哈登的数据堆代码),后来才发现每个球员比赛的年份不一样,于是乎才用了两个for循环来删掉指定的数据。

#自定义函数获取指定队员的比赛信息
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) #将比赛的数据放入data
#    print(data)
    for i in range(len(data)):
        if data[i]=='职业生涯常规赛平均数据':
#            print(data.index('职业生涯常规赛平均数据'))
            a=data[i+31]
            a=data.index(a)
    del(data[:a]) #清除a之前的所有数据
    for x in range(len(data)):
        if data[x]=='职业生涯季后赛平均数据':
#            print(data.index('职业生涯季后赛平均数据'))
            b=data[x]
            b=data.index(b)
#           del(data[b:])
    del(data[b:]) #清除b之后的所有数据
    return data

这个函数简直是绞尽脑汁,刚开始写入数据我是一个一个写的,后来又发现每个人的数据都错位(原谅我又是照着哈登来写的),昨天想了一个下午才利用这个for循环来建立表格的数据。(太喜欢用for循环,万能,对于我们这种小白来说)。

#自定义函数创建表格和表图
def player_chart(name,data,cur_path):
    workbook=xlsxwriter.Workbook(cur_path+'\\'+name+'chart.xlsx') #在指定路径创建表格文件
    worksheet=workbook.add_worksheet(name) #创建工作台
    bold=workbook.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]) #写入数据
    chart_col = workbook.add_chart({'type': 'line'}) #创建一个折线图
    #配置第一个系列数据  
    chart_col.add_series({
        'name': '='+name+'!$R$1', #设置折线描述名称
        'categories':'='+name+'!$A$2:$A$'+str(num), #设置图表类别标签范围
        'values': '='+name+'!$R$2:$R$'+str(num-1),    #设置图表数据范围
        'line': {'color': 'red'}, })   #设置图表线条属性
    #设置图标的标题和想x,y轴信息
    chart_col.set_title({'name': name+'生涯常规赛平均得分'}) 
    chart_col.set_x_axis({'name': '年份 (年)'}) 
    chart_col.set_y_axis({'name': '平均得分(分)'})
    chart_col.set_style(1) #设置图表风格
    worksheet.insert_chart('A14', chart_col, {'x_offset':25, 'y_offset':3,}) #把图标插入工作台中并设置偏移
    workbook.close()

以上都是几个比较重要的结构,我直接上源代码

#coding=utf-8
from bs4 import BeautifulSoup
import requests
import xlsxwriter
import os
import re


#自定义函数获取球队列表和相应的URL
def teamlists(url):
    name_list=[] #定义空列表放入所有球队名称
    teamurl_list=[] #定义空列表放入所有球队对应的URL
    html=requests.get(url)
    soup=BeautifulSoup(html.content,'lxml')
    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("请输入想查询的球队名:")
    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

#自定义函数获取队员列表和对应的URL
def playerlists(TeamUrl):
    playname_list=[] #定义空列表放入所有球员名称
    playurl_list=[] #定义空列表放入所有球员对应的URL
    html2=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("请输入球员名:")
    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

#自定义函数获取指定队员的比赛信息
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) #将比赛的数据放入data
#    print(data)
    for i in range(len(data)):
        if data[i]=='职业生涯常规赛平均数据':
#            print(data.index('职业生涯常规赛平均数据'))
            a=data[i+31]
            a=data.index(a)
    del(data[:a]) #清除a之前的所有数据
    for x in range(len(data)):
        if data[x]=='职业生涯季后赛平均数据':
#            print(data.index('职业生涯季后赛平均数据'))
            b=data[x]
            b=data.index(b)
#           del(data[b:])
    del(data[b:]) #清除b之后的所有数据
    return data

#自定义函数创建文件夹
def file_add(path):
    cur_path=path+'\\Basketball' #在指定路径建立文件夹
    try:
    	if not os.path.isdir(cur_path):#确认文件夹是否存在
    		os.makedirs(cur_path)       #不存在则新建
    except:
    	print("文件夹存在")
    return cur_path
#自定义函数创建表格和表图
def player_chart(name,data,cur_path):
    workbook=xlsxwriter.Workbook(cur_path+'\\'+name+'chart.xlsx') #在指定路径创建表格文件
    worksheet=workbook.add_worksheet(name) #创建工作台
    bold=workbook.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]) #写入数据
    chart_col = workbook.add_chart({'type': 'line'}) #创建一个折线图
    #配置第一个系列数据  
    chart_col.add_series({
        'name': '='+name+'!$R$1', #设置折线描述名称
        'categories':'='+name+'!$A$2:$A$'+str(num), #设置图表类别标签范围
        'values': '='+name+'!$R$2:$R$'+str(num-1),    #设置图表数据范围
        'line': {'color': 'red'}, })   #设置图表线条属性
    #设置图标的标题和想x,y轴信息
    chart_col.set_title({'name': name+'生涯常规赛平均得分'}) 
    chart_col.set_x_axis({'name': '年份 (年)'}) 
    chart_col.set_y_axis({'name': '平均得分(分)'})
    chart_col.set_style(1) #设置图表风格
    worksheet.insert_chart('A14', chart_col, {'x_offset':25, 'y_offset':3,}) #把图标插入工作台中并设置偏移
    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)

效果展示:
在这里插入图片描述

第四步 总结问题

大家可以看到,对于beautifulsoup和正则表达式我不太熟悉,所以跟我一样的小白一定要利用空闲时间多看看,但也告诉我们代码是死的人是活的,要多利用其它的办法去解决眼前的问题,唯一一项我没有解决成功的问题就是我导入的折线图没办法显示出X轴的数据,我试过很多次,看了很多博客都没找到解决办法,也有可能是Xlsxwriter不够熟,留给评论区的大神帮我解决。最后还是希望大家好好学习天天向上。

xlsxwriter模块参考文献:
python写入excel(xlswriter)–生成图表

发布了2 篇原创文章 · 获赞 24 · 访问量 4479

猜你喜欢

转载自blog.csdn.net/weixin_45346759/article/details/104876228