python告诉你ti8 dota2英雄bp
恭喜OG成为ti8冠军,很可惜这次偶数年ti8中国队LGD与冠军失之交臂。
上学那会儿还是个dota的玩家,现在已经不玩了,对于这种国际性的赛事还是会比较关注的,这篇文章就是爬取ti8期间,bp英雄的统计(b是ban的简称:禁止一个英雄上场;p是pick的简称:挑选英雄上场)。
python爬虫之前写过几篇文章的,都是用requests+ BeautifulSoup 进行页面解析获取数据的。
一如既往的,找到这样的页面,但是却解析不到这些数据。
再仔细一看,原来这些数据是js动态加载渲染的,可以看到是接口请求来的数据,庆幸的是这个接口不需要cookie之类的验证信息的,直接get请求可以拿到数据,这样处理起来就方便的,对照页面可以知道json格式的各字段名。
json结构分析
数据来源是接口,直接
response = requests.get(url)
data = json.loads(response.text)
通过json.loads 去解析string类型的数据,主要数据格式如下:
{
total: 402,
data: [{
match_id: 4080856812,
radiant: {
team_id: 15,
name: "PSG.LGD",
tag: "PSG.LGD",
country_code: "CN",
score: 34,
bans: [{ //每个英雄数据
name: "spectre",
name_cn: "幽鬼",
id: 67
}, ...],
picks: [{
name: "earthshaker",
name_cn: "撼地者",
id: 7
}, ...]
},
dire: {
team_id: 2586976,
name: "OG",
tag: "OG",
country_code: "US",
score: 35,
bans: [{
name: "tiny",
name_cn: "小小",
id: 19
}, ...],
picks: [{
name: "furion",
name_cn: "先知",
id: 53
}, ...]
},
radiant_win: 0,
end_time: "2018-08-26 10:51"
}, ...]
}
每个item含radiant、dire ,其中radiant_win: 1,
代表radiant 获胜,0 则代表dire 获胜。bans里面的是ban的英雄数据列表,picks里面是pick的英雄数据列表。
这里是用循环不断去请求获取的,每次的数据是20条,可以改变size改变条数。
page = 1
while True:
url = "https://www.dotamore.com/api/v1/league/matchlist?league_id=9870&page=%d&size=20" % page
response = requests.get(url)
data = json.loads(response.text)
page += 1
for item in data["data"]:
# 比赛从8月16开始,小于这个时间生成excel,跳出循环
if item["end_time"] < "018-08-16 00:00":
//生成excel
...
return
//bp数据
...
bp数据
每项里面的bans、picks数据都要处理,每个英雄是一条记录,重复的就+1,所以给每个英雄count 的属性,记录次数。
# item 指radiant 或dire 的bans、picks列表数据
def bp(item, bp_dict):
if item is None:
return
# 遍历bans 或picks 数据
for i, bp in enumerate(item):
key = bp["name"]
# 如果这个英雄已存在,count+1
if key in bp_dict.keys():
bp_dict[key]["count"] = bp_dict[key]["count"] + 1
else: # 不存在就记录一条数据
bp_dict[key] = copy.deepcopy(bp)
bp_dict[key].update(count=1)
return bp_dict
每条英雄数据是个键值对字典,键是name 属性即英文名字,值就是bans、picks里的各项英雄数据,顺便加上了count 属性。每个英雄数据存在dict()
{ //每条英雄数据
name: "tiny",
name_cn: "小小",
id: 19,
count:1
}
分别获取两只队伍bp数据存放
b_dict = dict()
p_dict = dict()
# ban的数据
bp(item["radiant"]["bans"], b_dict)
bp(item["dire"]["bans"], b_dict)
# pick的数据
bp(item["radiant"]["picks"], p_dict)
bp(item["dire"]["picks"], p_dict)
也可以统计所有英雄的出场次数,非搬即选bp_list。
还可以获取冠军队伍的bp情况,team_id 即队伍的id。
if item["radiant_win"] == 0:
if item["dire"]["team_id"] == "2586976":
bp(item["dire"]["bans"], b_win_dict)
bp(item["dire"]["picks"], p_win_dict)
else:
if item["radiant"]["team_id"] == "2586976":
bp(item["radiant"]["bans"], b_win_dict)
bp(item["radiant"]["picks"], p_win_dict)
生成excel
以上数据我们得到的是字典,里面有各英雄的bp次数,现在要对这些数据进行排序,按次数从大到小排序,这里就用到sorted()
方法
# x[0]是根据键排序,x[1]是根据值,这里的值是字典,取["count"]项排序,得到的是元祖的list
new_b_dict = sorted(b_dict.items(), key=lambda x: x[1]["count"], reverse=True)
得到的是数组,生成表格在之前这篇文章中有过使用,这里使用的是xlsxwriter
三方库来操作excel 表格的。
# 创建excel表格
file = xlsxwriter.Workbook("dota.xlsx")
# 创建工作表1
sheet1 = file.add_worksheet("sheet1")
# 创建表头
headers = ["图片", "英雄", "ban", "", "图片", "英雄", "pick", "", "图片", "英雄", "bp_all"]
for i, header in enumerate(headers):
# 第一行为表头
sheet1.write(0, i, header)
第一行是表头,对应的每一列填充数据
def insert_data(sheet1, headers, bp_list, col1, col2, col3):
for row in range(len(bp_list)): # 行
# 设置行高
sheet1.set_row(row + 1, 30)
for col in range(len(headers)): # 列
if col == col1: # 英雄图片,根据id获取
url = "http://cdn.dotamore.com/heros_id_62_35/%d.png" % bp_list[row][1]["id"]
image_data = BytesIO(urlopen(url).read())
sheet1.insert_image(row + 1, col, url, {"image_data": image_data})
if col == col2: # 英雄名
name = bp_list[row][1]["name_cn"]
sheet1.write(row + 1, col, name)
if col == col3: # 统计次数
count = bp_list[row][1]["count"]
sheet1.write(row + 1, col, count)
excel 表格生成,还可以插入柱状图。
def insert_chart(file, sheet1, bp_list, name, M, col_x, col_y):
chart = file.add_chart({"type": "column"}) # 柱状图
chart.add_series({
"categories": ["sheet1", 1, col_x, len(bp_list), col_x], # 图表类别标签范围,x轴,这里取英雄的名字,即英雄名字那一列,行数根据数据列表确定
"values": ["sheet1", 1, col_y, len(bp_list), col_y], # 图表数据范围,y轴,即次数那一列,行数根据数据列表确定
"data_labels": {"value": True},
})
chart.set_title({"name": name}) # 图表标题
chart.set_size({"width": 2000, "height": 400})
chart.set_x_axis({'name': '英雄'}) # x轴描述
chart.set_y_axis({'name': '次数'}) # y轴描述
chart.set_style(3) # 直方图类型
sheet1.insert_chart(M, chart) # 在表格M处插入柱状图
效果图:
这里只是简单的对数据进行筛选展示,这些数据还是可以用来做更多的数据分析的,数据来源:刀魔数据。
github地址:https://github.com/taixiang/py_dota
最后放上lgd的图片,希望他们明年能在ti9上再干回来
欢迎关注我的博客:https://blog.manjiexiang.cn/
更多精彩欢迎关注微信号:春风十里不如认识你
有个「佛系码农圈」,欢迎大家加入畅聊,开心就好!
过期了,可加我微信 tx467220125 拉你入群。
python告诉你ti8 dota2英雄bp的更多相关文章
- 抖音很火的存钱计划,让python告诉你总共可以存到多少钱!
抖音上有个很火的存钱计划,说是第一天存1块钱,第二天存2块钱,第三天存3块钱.....依此类推存365天,总共可以存到多少钱,我们现在用python告诉你怎么做: #定个初始存入金额 money = ...
- Python爬取 | 王者荣耀英雄皮肤海报
这里只展示代码,具体介绍请点击下方链接. Python爬取 | 王者荣耀英雄皮肤海报 import requests import re import os import time import wi ...
- 用Python爬取"王者农药"英雄皮肤
0.引言 作为一款现象级游戏,王者荣耀,想必大家都玩过或听过,游戏里中各式各样的英雄,每款皮肤都非常精美,用做电脑壁纸再合适不过了.本篇就来教大家如何使用Python来爬取这些精美的英雄皮肤. 1.环 ...
- 用Python爬取"王者农药"英雄皮肤 原
padding: 10px; border-bottom: 1px solid #d3d3d3; background-color: #2e8b57; } .second-menu-item { pa ...
- 利用python爬取王者荣耀英雄皮肤图片
前两天看到同学用python爬下来LOL的皮肤图片,感觉挺有趣的,我也想试试,于是决定来爬一爬王者荣耀的英雄和皮肤图片. 首先,我们找到王者的官网http://pvp.qq.com/web201605 ...
- 充气娃娃什么感觉?Python告诉你
上期为大家介绍了requests库的基本信息以及使用requests库爬取某东的商品页,收到了很多同学的反馈说期待猪哥的更新,猪哥感到非常开心,今天就带大家来玩一把刺激的! 一.需求背景 在实际开发过 ...
- 10分钟用Python告诉你两个机器人聊天能聊出什么火花
欲直接下载代码文件,关注我们的公众号哦!查看历史消息即可! 现在不是讲各种各样的人工智能嘛,AI下棋,AI客服,AI玩家--其实我一直很好奇,两个AI碰上会怎样,比如一起下棋,一起打游戏-- 今天做个 ...
- python告诉你啥是佩奇
被<啥是佩奇>这支广告片刷屏了. 佩奇明明是个喜剧角色, 但是看哭了所有人. <啥是佩奇>??? 效果图如下: # -*- coding:utf-8 -*- from turt ...
- 做直播能有多赚钱,Python告诉你
前面我们介绍了APP爬虫环境的搭建和mitmproxy工具的简单使用,这次我们要来一个简单的APP爬虫,尝试一下APP爬虫的简单实用,顺便让我们看看喜马拉雅上的主播到底有多赚钱. APP爬虫一般分为两 ...
随机推荐
- 动态规划----最长公共子序列(LCS)问题
题目: 求解两个字符串的最长公共子序列.如 AB34C 和 A1BC2 则最长公共子序列为 ABC. 思路分析:可以用dfs深搜,这里使用到了前面没有见到过的双重循环递归.也可以使用动态规划,在建 ...
- 【从零开始搭建自己的.NET Core Api框架】(二)搭建项目的整体架构
系列目录 一. 创建项目并集成swagger 1.1 创建 1.2 完善 二. 搭建项目整体架构 三. 集成轻量级ORM框架——SqlSugar 3.1 搭建环境 3.2 实战篇:利用SqlSuga ...
- [Swift]LeetCode398. 随机数索引 | Random Pick Index
Given an array of integers with possible duplicates, randomly output the index of a given target num ...
- [Swift]LeetCode433. 最小基因变化 | Minimum Genetic Mutation
A gene string can be represented by an 8-character long string, with choices from "A", &qu ...
- spring boot - 整合jpa多对对关系保存和查询示例
pojo: package com.example.zs.springDataJpa; import org.hibernate.annotations.Proxy; import javax.per ...
- BBS论坛(十八)
18.首页轮播图实现 (1)front/css/front_base.css .main-container{ width: 990px; margin: 0 auto; overflow: hidd ...
- 上下div高度动态自适应--另类处理方案
这段时间在工作中遇到一个看似较为棘手的问题.问题描述:查询报表页面分为上下两部分,上部分为条件输入区域,下部分为报表展示区域.客户要求做到默认满屏(但要动态适应不同的窗体大小,也就是浏览器窗体用户会手 ...
- Java 多线程(三)—— 线程的生命周期及方法
这篇博客介绍线程的生命周期. 线程是一个动态执行的过程,它也有从创建到死亡的过程. 线程的几种状态 在 Thread 类中,有一个枚举内部类: 上面的信息以图片表示如下: 第一张图: 第二张图:把等待 ...
- 华为oj之等差数列前n项和
题目: 等差数列 热度指数:1010 时间限制:1秒 空间限制:32768K 题目描述 功能: 对于等差数列 2,5,8,11,14- 输入: 正整数N >0 输出: 求等差数列前N项和 返回: ...
- Lucene 09 - 什么是Lucene的高亮显示 + Java API实现高亮显示
目录 1 什么是高亮显示 2 高亮显示实现 2.1 配置pom.xml文件, 加入高亮显示支持 2.2 代码实现 2.3 自定义html标签高亮显示 1 什么是高亮显示 高亮显示是全文检索的一个特点, ...