LPL比賽數據可視化,完成這個項目,用盡了我的所有Python知識


LPL比賽數據可視化

 

效果圖

完成這個項目,我感覺我已經被掏空了,我幾乎用盡了我會的所有知識
html+css+javascript+jQuery+python+requests+numpy+mysql+pymysql+json+ajax+flask+echarts
在這個過程中,並不是那么順利,遇到了很多坑,好在全部都已經解決
在整個頁面全部功能運行成功的那一刻,我感覺幸福極了

"""
當然在學習Python的道路上肯定會困難,沒有好的學習資料,怎么去學習呢? 
學習Python中有不明白推薦加入交流Q群號:928946953 
群里有志同道合的小伙伴,互幫互助, 群里有不錯的視頻學習教程和PDF!
還有大牛解答!
"""

 

 

 


下面我就帶領大家實踐一下,怎么從無到有

如果覺得涉及的知識太多,實踐起來困難的同學.不要怕,我專門做了一期視頻一分鍾上手此項目點我觀看視頻



需要用到的Python第三方庫:flask,requests,pymysql,numpy


聽說看着源碼讀文章絕配哦Github

 


點我直達可視化頁面

繪制前端頁面

整個頁面可划分為10個盒子,使用HTML和CSS就可以把最基礎的框架搭建出來,大家都是pink老師的學生,怎么在頁面中寫盒子我就不多說了,我主要講解一下如何將echarts的圖表插入到頁面中來

 

圖1

什么是Echarts

Echarts官方網站
ECharts 是一個使用 JavaScript 實現的開源可視化庫,涵蓋各行業圖表,滿足各種需求

ECharts 遵循 Apache-2.0 開源協議,免費商用

ECharts 兼容當前絕大部分瀏覽器(IE8/9/10/11,Chrome,Firefox,Safari等)及兼容多種設備,可隨時隨地任性展示

第一個 ECharts 實例

第一個 ECharts 實例源碼

!!!!!!

使用Echarts的前提是你需要掌握HTML和Javascript的知識,畢竟Echarts是基於JS開發
觀察源碼不難發現,引入了外部文件[echarts.js] 如果不引入,程序將無法正常運行
基於准備好的div,綁定事件,初始化echarts實例
指定圖表的配置項和數據,即可顯示圖表
大致流程:引入所需文件,在HTML定義好div盒子,在JS中綁定事件,初始化echarts實例,指定圖表的配置項和數據

項目中的Echarts

1.引入所需文件

 

圖2

說明:上面第一個實例將echarts的代碼寫在了HTML文件中,而我為了后期維護起來方便,就分開寫了,所以需要引入[js.js]文件,也就是我把關於echarts的代碼都寫在了[js.js]文件中

2.在HTML定義好div盒子

 

圖3

3.在JS中綁定事件,初始化echarts實例

 

圖4

4.指定圖表的配置項和數據

代碼過多,請到源碼中查看

Echarts部分小總結

Echarts部分不是很難,直接到Echarts官網實例中找你想要的圖表,然后復制代碼,修改圖表的配置和數據即可。我知道你肯定要問“代碼中的一些屬性我根本就不知道怎么去使用,怎么辦嘛” 不要方,請到Echarts官網文檔查看

項目中一共用了5種Echarts圖表,使用的方法大同小異,我相信你可以舉一反三

 

前端的頁面繪制完畢后,你會發現一個問題。數據都寫死的,而比賽數據幾乎每天都在更新。每天去源碼中修改對應的數據部分,過不了幾天我想你肯定會厭倦。解決的方法肯定是有的,不光只是爬蟲,還要向Echarts中插入數據(肯定不是手動插,而是機器插)。欲知后事如何,請往下看

爬取比賽數據

在講解爬取數據之前,我還是想簡單介紹一下什么是爬蟲,回答大家對於爬蟲的一些誤解;假定大家都有一定的爬蟲基礎

什么是爬蟲,爬蟲違法嗎?

數據從何而來

點我查看官網比賽數據

 

圖5


這個網站很特別,是一個動態的網站。如果說只是簡單的使用requests獲取頁面的源碼;雖然可以獲取到數據,但是數據只有當前顯示的一頁。我最開始的想法是使用selenium這個可以操控瀏覽器的第三方庫,進行數據的獲取。代碼寫完后,獲取數據沒什么問題,就是速度太慢了,我也利用requests重新寫了爬蟲程序,速度提升非常明顯(selenium用時20s,requests用時2s;兩個程序還包括了將數據寫入數據庫的代碼)

所有,selenium版本的爬蟲我不會講,主要還是講解requests的版本


現在,我們來到官網,右鍵點擊檢查(如果是谷歌瀏覽器,按F12也可以),點擊【Network】

 

圖6


按CTRL+R 刷新一下
在【name】下方找到【
LOL_MATCH2_MATCH_TEAMRANK_LIST_134_7_8.js】,接着點擊【Preview】,你就會看到這么一個界面

 

圖7


觀察右邊的數據,是不是就是戰隊的信息,只不過就是用json包裝起來了而已,利用Python簡單處理一下就能獲取到你想要的數據。這些數據是用接口形式傳輸的,我們就可以直接爬取接口

點擊旁邊的【Headers】,復制【Request URL】后面的網址,我們來到Pycharm

 

圖8

我們打印一下請求的網址

import requests def get_info(url): headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36 LBBROWSER'} response = requests.get(url=url,headers=headers) return response.text info = get_info('https://lpl.qq.com/web201612/data/LOL_MATCH2_MATCH_TEAMRANK_LIST_134_7_8.js') print(info)

Python

 

輸出結果:

 

圖9

可以看出所有的戰隊信息已經獲取成功,可是輸出的內容是一個str(字符串)對象,我們需要使用json.loads()函數將str對象轉換為dict(字典)對象。再使用字典和列表的方法就可以將想要的數據提取出來,並且存放到另外一個字典里面

import requests import json def get_info(url): headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36 LBBROWSER'} response = requests.get(url=url,headers=headers) return response.text info = get_info('https://lpl.qq.com/web201612/data/LOL_MATCH2_MATCH_TEAMRANK_LIST_134_7_8.js') info = json.loads(info) #將str對象轉換為dict(字典)對象 info_msg = info['msg'] #使用字典里面的鍵獲取對於的值 #隊名 teamName = [data['sTeamName'] for data in info_msg] #出場次數 out_count = [data['iAppearancesFrequency'] for data in info_msg] #勝場 win = [data['iWin'] for data in info_msg] #敗場 loss = [data['iLoss'] for data in info_msg] #勝率 win_rate = [int(str((int(data['iWin'])/(int(data['iWin'])+int(data['iLoss'])))*100)[:2]) for data in info_msg] #總擊殺 kill_sum = [data['iKill'] for data in info_msg] #總死亡 death_sum = [data['iDeath'] for data in info_msg] #插眼 placed_eye = [int(float(data['sAveragingWardPlaced']))for data in info_msg] #排眼 killed_eye = [int(float(data['sAveragingWardKilled']))for data in info_msg] infos_list = [('隊名',teamName),('出場次數',out_count),('勝場',win), ('敗場',loss),('勝率',win_rate),('總擊殺',kill_sum), ('總死亡',death_sum),('插眼',placed_eye),('排眼',killed_eye)] info_dict = {key:value for key,value in infos_list} print(info_dict)

Python

 

輸出結果:

 

圖10


在上面的程序當中,我運用列表推導式,字典推導式,很輕松的就拿到了想要數據。如果你還看不懂推導式,你可以到我這篇文章看看Python高級編程之列表推導式、字典推導式、集合推導式

其實,列表推導式還有更簡單的寫法,你可以去源碼當中的【spider_api.py】文件中,第125行代碼查看,117-122行注釋的代碼就是未優化的代碼,留個小小的彩蛋,期待你去發現

聰明的你肯定已經發現了,這只是LPL戰隊的數據,那么隊員和英雄的數據接口在哪里呢,剛才檢查網頁的時候,也沒有發現.不要方,接着往下看

 

動態網站,其他數據接口在哪里

我們回到官方網站,點擊【個人數據】

 

圖11


接着右鍵檢查,找到【
LOL_MATCH2_MATCH_PERSONALRANK_LIST_134_7_8.js】

 

圖12


獲取數據的方法就和上面的類似了,我相信你可以舉一反三


然而,獲取英雄數據就不是那么順利了
還是回到官網,點擊【英雄數據】
還是右鍵檢查,找到【
LOL_MATCH2_MATCH_HERORANK_LIST_134_7_8.js】

 

圖13


你會驚奇的發現,為什么沒有英雄的名字,而只有【iChampionId】和其他數據
於是,我們大膽的猜測,這些【iChampionId】會不會是英雄對應的ID呢?

尋找英雄名稱

想查看英雄的名稱,我腦袋里面第一個蹦出了的想法就是英雄聯盟官網
老規矩,右鍵檢查,找到【hero_list.js】,Amazing呀!

 

圖14


你仔細看,發現英雄名稱前面有個【heroId】,會不會就和我們剛才看到的【iChampionId】相對應呢?
你不用去對比啦,我已經對比過了,就是相對應的,嘿嘿

 


雖然已經找到英雄名稱,但是新的問題又來了
從兩個接口獲取到的數據,怎么保證【iChampionId】的英雄匹配到正確的名稱
如何獲取數據,我就不多嘴了,詳細代碼請查看源碼.我這里主要講解一下如何匹配正確的英雄名稱

name = [] for i in hero_key_id_top60: for j in hero_name_id_list: if i == j :  #由於從lpl數據頁面無法獲取到英雄名稱,只能獲取到對應的id  #一層循環是pick率前60的英雄id,二層是所有英雄的的id  #通過if判斷,將pick率前60的英雄寫入到指定列表中 name.append(hero_name_list[hero_name_id_list.index(j)])

Python

 

【hero_key_id_top60】中的內容:

 

圖15


【hero_name_id_list】中的內容:

 

圖16


【hero_name_list】中的內容:

 

圖17


【name 】中的內容:

 

圖18

數據已到位,下一步導入數據庫

數據庫交互

首先,請在你的電腦上面創建一個名為【lpl】的數據庫,不需要建表,后面我會講解如何用pymysql建表

導入數據

我們需要連接自己的數據庫
代碼如下,值得注意的是,passwd='你自己數據庫的密碼'
如果說看不懂代碼,可以先去了解一下MySQL和pyMySQL

import pymysql def mysql(): db = pymysql.connect( host='localhost', user='root', passwd='123456', db='lpl', charset='utf8') cur = db.cursor() return db,cur

Python

 

數據庫連接成功后,我們以【戰隊排行榜】為例

db, cur = mysql()
    try: # 是否存在這個表,若存在就刪除,【戰隊排行榜前五】為表的名稱 cur.execute("DROP TABLE IF EXISTS 戰隊排行榜前五") # 創建表sql語句 set_sql_top5 = """ create table 戰隊排行榜前五( 戰隊名稱 varchar(20), 出場次數 varchar(10), 勝率 varchar(10)) """ # 執行sql語句 cur.execute(set_sql_top5) db.commit() # 保存 # 准備寫入數據的sql語句 save_sql_top5 = "INSERT INTO 戰隊排行榜前五 values(%s,%s,%s);" # 寫入數據庫,參數一:寫入的sql語句 參數二:數據,類型為列表,里面的元素類型是元組 cur.executemany(save_sql_top5,info_list) db.commit() print("寫入數據庫成功") except Exception as e: print("創建數據庫失敗:case%s" % e)

Python

 

【info_list】當中的數據

 

圖19

數據庫中的數據

 

圖20

取出數據

數據庫還是需要連接的,我們任然以【戰隊排行榜】為例

import pymysql def mysql(): db = pymysql.connect( host='localhost', user='root', passwd='123456', db='lpl', charset='utf8') cur = db.cursor() return db,cur def query(sql): db,cur = mysql() cur.execute(sql) #執行傳入的sql語句 res =cur.fetchall() #獲取sql語句字段中的所有數據 return res #sql語句,從【戰隊排行榜前五】這張表中,選擇戰隊名稱,出場次數,勝率 sql_wings = 'SELECT 戰隊名稱,出場次數,勝率 FROM 戰隊排行榜前五' infos_wings = query(sql_wings) #取出數據 #print(infos_wings) : (('TES', '40', '75%'), ('JDG', '43', '72%'), ('V5', '49', '61%'), ('IG', '44', '59%'), ('SN', '52', '59%')) name = [info[0] for info in infos_wings] out_count = [info[1] for info in infos_wings] win_rate = [info[2] for info in infos_wings] infos_list = [('name', name), ('outcount', out_count), ('winRate', win_rate)] #為什么最后要轉換成字典的形式,我會在后面向前端傳輸數據的時候講解 infos_dict = {key: value for key, value in infos_list} #print(infos_dict) #{'name': ['TES', 'JDG', 'V5', 'IG', 'SN'], 'outcount': ['40', '43', '49', '44', '52'], 'winRate': ['75%', '72%', '61%', '59%', '59%']}

Python

Web程序開發

什么是Web程序

Web應用程序是一種可以通過Web訪問的應用程序。Web應用程序的一個最大好處是用戶很容易訪問應用程序。用戶只需要有瀏覽器即可,不需要再安裝其他軟件
能夠開發web程序的編程語言有很多,比如Java,Php,Python等
而我們選擇用Python進行開發,使用Falsk框架進行快速開發

什么是Falsk

Flask是一個使用 Python編寫的輕量級Web應用框架。其WSGl( Python Web Server Gateway Interface)工具包采用 Werkzeug,模板引擎則使用 Jinja2,是目前十分流行的Web框架
這里給大家推薦一期視頻,Flask快速入門.由於我的能力有限,還請大家花點時間將視頻看完,再接着往后看文章

使用Flask連接前端頁面

假定大家已經看完了視頻,嘿嘿

使用pycharm創建一個flask項目,會自動幫我們生成兩個文件夾【templates】【static】和一個python文件【app.py】
我們需要將寫好的HTML文件放在【templates】目錄下,CSS、JS和所用到的圖片放在【static】目錄下,如下圖所示

 

圖21

值得注意的是,也是一個坑,HTML文件當中,引用的外部文件,文件地址一定要去修改。因為我們是先寫好的前端頁面,而flask當中需要我們將外部文件都放在【static】當中

注意事項

引入模板

這里所說的模板,就是我們寫好的HTMl文件,只不過需要使用render_template()將其引入

import lpldata from flask import Flask,render_template app = Flask(__name__) LPL = lpldata.Lpl_Data()#從數據庫獲取數據 @app.route('/')#默認路由 def hello_world(): return render_template("index.html")#引入模板

Python

 

使用Ajax傳輸數據

什么是Ajax

Ajax是Asynchronous Javascript and XML的簡稱,通過Ajax向服務器發送請求,接收服務器返回的json數據,然后使用 Javascript修改網頁,來實現頁面局部數據更新。使用 Jquery框架可方便的編寫Ajax代碼,需要 Jquery.js文件

基本格式

$.ajax({
    type:"post", //請求類型 url:"/目標路由", //請求地址 data:{}, //數據 datatype:"json", success:function (data) { //請求成功的回調函數,data是返回的數據 }, error:function () { //請求失敗時執行 } })

JavaScript

 

我們先到app.py文件中,定義好一個路由(/wingsvd),methods添加一個'post',這里以【戰隊勝負圖表】為例

@app.route('/wingsvd',methods=['GET','POST']) def wings_vd(): return LPL.get_wings_vd()

Python

 

LPL.get_wings_vd(),你可以到lpldata.py文件查看相關的代碼。主要功能就是從數據獲取數據,並且將數據整理好后,存到字典里面,最后使用json.dumps()將dict(字典)對象轉換為json對象,最為函數的返回值返回

現在回到Ajax的部分,你可以到【js.js】文件中359行查看

function echarts_4() { // 基於准備好的dom,初始化echarts實例 var myChart = echarts.init(document.getElementById('echart4')); var lpl = {}; $.ajax({ url:'/wingsvd', //這里的地址是不是很眼熟,沒錯就是剛才定義的路由地址 data: {}, type: 'POST', async: false, dataType:'json', success: function (data) { lpl.name = data.name; // 使用json的方法,提取剛才LPL.get_wings_vd()返回的數據 lpl.victory = data.victory; lpl.defeat = data.defeat; lpl.winRate = data.winRate; ......

JavaScript

 

數據提取成功后,就可以在后面的echarts代碼中修改對應的配置,圖表就可以顯示出數據啦

這里以圖表的X軸為例

xAxis: [ { type: "category", data: lpl.name, //上面的代碼是不是也有它呀,有就對啦 axisLine: { lineStyle: {color: "rgba(255,255,255,.1)"}}, axisLabel: { textStyle: {color: "rgb(255,255,255)", fontSize: '16', }}, }, ],

JavaScript

 

所有的圖表傳輸數據的操作方法都是一樣的,先在【app.py】中創建路由,返回你需要的數據,再到【js.js】當中寫Ajax和Echarts的代碼

最后的勝利

所有的准備工作完成后,我們就只剩最后一步啦!

if __name__ == '__main__': app.run(debug=True)

Python

 

右鍵,運行,點擊下方的地址,可視化的頁面就呈現在了你的眼前

 

 

圖24


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM