用爬蟲抓取崑崙決所有選手信息並保存為PDF檔案!(淺談搏擊運動數據分析)

GitHub地址:QuantumLiu/KLFSpider

背景

本人是個偽拳迷,520之夜我跑到「寶馬雕車香滿路」的某豪車交易中心,現場觀看了崑崙決「」讓子彈飛」MMA比賽,不但看夠了豪車美女(受夠了刺激)

欣賞了精彩刺激的比賽

更是見證了姜老闆和龍武探討摔跤哲學

回家之後興奮勁沒過去,睡不著。我一直相信萬物皆可量化萬物終將被量化,突然想試試數據技術能在搏擊運動上做些什麼。於是就連夜寫了一個爬蟲從崑崙決官網抓取了使用選手的公開信息作為一個開始。

正文

在本文中,我們從崑崙決爬取了全部350位的公開信息,包括姓名、年齡、戰績、身高體重等。並保存為 `.md` 的markdown文件,並進一步使用Python-markdown 庫將markdown文本轉換為HTML文件並列印為pdf文件。

一.分析網頁結構並確定處理流程

進入崑崙決首頁,點擊選手選項卡下的「運動員」。

不出所料,對應的網頁是一個索引性質的各個選手的簡介頁面。

但是我們注意到,這個網頁並不是一次載入完成的,在底部有一個「載入更多」的按鈕

通過開發工具,我們知道這是一個xxxx/n.html形式的鏈接,而且n是從2

開始的。

所以我們可以推測這個簡介頁面原理如下:

n=1n載入xxxx/1.htmlnwhile n<n_max:n 點擊「載入更多」n n+=1n load(xxx/n.html)n

我們稱xxxx/n.html為簡介內容鏈接。如果我們枚舉所有的簡介內容鏈接,就可以得到所有選手的簡介和詳情頁面的入口。

我們先嘗試一下當n=1是頁面是否存在並試出最大頁數。

我們看到當n=1時,簡介內容鏈接的內容和簡介頁面的核心內容是一樣的(亂碼應該是因為ISO編碼問題),同時我們試出來最大有效頁數是26。

接下來我們進入每個選手的詳情頁面,所有我們需要的信息都在這個頁面

現在我們明確了網頁的結構,抓取的流程也就隨之確定下來了

抓取流程:

獲取所有簡介內容鏈接n抓取所有選手詳情鏈接nfor 詳情鏈接 in 所有選手詳情鏈接:n 抓取信息並處理n return 信息n

二.具體實現

1.正則表達式

首先我們要抓取的所有的詳情鏈接。

通過開發工具,我們看到在簡介頁面中每個選手的詳情鏈接:

於是可以確定詳情頁面的正則:

r_player_info_page=r</a></li><li><a href="(.*?)" title="#詳情頁的正則n

接下來我們查看選手詳情頁的代碼來獲得每項屬性的正則。

我們驚喜的發現包裹每項信息的字元非常的規律與簡潔!

我們不妨先得到所有屬性名稱的list再得到所有屬性的內容

r_att=r <li><span>(.*?)</span>#屬性名稱正則natt_list=re.findall(r_att,page_text)[0:8]nfor att in att_list:n r=r<li><span>+att+</span>([sS]*?)</li>#屬性內容正則n

其中使用([sS]*?)匹配符是因為簡介信息會有換行符n,所以要匹配所有的包括換行符在內地符號。

我們看到的對於外國選手,姓名屬性只有中文譯名,所以我們還需要英文名。

全名、戰績以及排名的正則:

r_name=r<div class="uk-width-2-3 info"> <h1><img src=".*?">(.*?)</h1> nr_gain=r<h3 class="chengji">(.*?)</h3>nr_rank=r<!-- <h3 class="paiming">(.*?)</h3>n

最後,我們得到選手圖片鏈接的正則

r_pic=r<div class="uk-width-1-3 avatar"> <img src="(.*?)" alt=n

以上,我們完成了對所要抓取信息的正則的分析,接下來我們編寫一個完整的爬蟲程序。

2.完整程序

程序邏輯:

定義一個player類,每個運動員看做一個player對象。

按照我的習慣,我選擇使用requests庫和multiprocessing來實現這個爬蟲。

通過並行遍歷每個運動員的詳情頁處理數據,將信息保存為Markdown格式

最後,我們使用 markdown庫將markdown文本轉換為html文件,再使用印表機列印為pdf文檔。

# -*- coding: utf-8 -*-n"""nCreated on Sun May 21 20:29:40 2017nn@author: Quantum Liun"""nnimport requestsnimport renimport picklenimport markdownnimport codecsnfrom multiprocessing import Pool,cpu_count,freeze_supportnimport osnclass player():#每個運動員都是一個player對象n def __init__(self,info_dic,info,pic_url):n self.info_dic=info_dicn self.info=infon self.pic_url=pic_urln self.name=self.info_dic.get(姓名)n self.dir_name=./+self.info_dic.get(姓名)n self.info_file=self.dir_name+/+info.mdn def mkdir(self):#創建運動員目錄n if not os.path.exists(self.dir_name):n os.mkdir(self.dir_name)n def saveimg(self):#保存頭像圖片n self.pic_path=self.dir_name+/+head.pngn data=requests.get(self.pic_url).contentn with open(self.pic_path,wb) as f:n f.write(data)n def saveasmd(self):#生成個人.md文檔n with open(self.info_file,w,encoding=utf-8) as f:n head=# +self.info_dic.get(姓名)n pic_link= r![pic](./head.png) rn upic_link= r![pic](+self.pic_path+) rn self.mdtext=head+pic_link+self.info#個人markdown文本內容n self.umdtext=head+upic_link+self.info#合集的markdown內容n f.write(self.mdtext)ndef player_info(page_text=):n info=n r_att=r <li><span>(.*?)</span>#屬性名稱正則n r_name=r<div class="uk-width-2-3 info"> <h1><img src=".*?">(.*?)</h1> n r_gain=r<h3 class="chengji">(.*?)</h3>n r_rank=r<!-- <h3 class="paiming">(.*?)</h3>n r_pic=r<div class="uk-width-1-3 avatar"> <img src="(.*?)" alt=n att_list=re.findall(r_att,page_text)[0:8]n att_list.remove(社交)#社交這一項信息無用n dic={}.fromkeys(att_list)n pic_url=http://www.kunlunjue.com+re.findall(r_pic,page_text)[0]n name=re.findall(r_name,page_text)[0]n gain=re.findall(r_gain,page_text)[0]n rank=re.findall(r_rank,page_text)[0]n dic[全名]=namen dic[戰績]=gainn dic[排名]=rankn info+=全名:+name+ r+戰績:+gain+ r+排名:+rank+ rn for att in att_list:n r=r<li><span>+att+</span>([sS]*?)</li>#屬性內容正則n value=re.findall(r,page_text)[0].replace(n, r)#將換行改為markdown格式n info+=att+:+value+ rn dic[att]=valuen return (dic,info,pic_url)ndef processing(page_url=):#想不出函數名的時候就叫它processing吧n page_text=requests.get(page_url).textn info_dic,info,pic_url=player_info(page_text=page_text)n p=player(info_dic,info,pic_url)n p.mkdir()n p.saveimg()n p.saveasmd()n return p#返回一個player對象nif __name__ == __main__:n freeze_support()n #全體自由搏擊選手或者全部項目運動員的索引頁的HTML內容n free_sparring_only=Truen index_root=(http://www.kunlunjue.com/portal/player/player_fall/level/all/national/all/height/all/order/any/desc/des/type/%E8%87%AA%E7%94%B1%E6%90%8F%E5%87%BB/p/ if free_sparring_only else http://www.kunlunjue.com/portal/player/player_fall/level/all/national/all/height/all/order/any/desc/des/type/all/p/)n ran=(26 if free_sparring_only else 37)n all_page_text=.join([requests.get(page).text.encode(ISO-8859-1).decode(utf-8) for page in [index_root+str(int(i+1))+.html for i in range(ran)]])n r_player_info_page=r</a></li><li><a href="(.*?)" title="#詳情頁的正則n info_page_list=[http://www.kunlunjue.com/+url for url in re.findall(r_player_info_page,all_page_text)]#所有詳情頁n pool=Pool(cpu_count())#根據cpu最大線程數創建並行池n player_list=[]n for page_url in info_page_list:n player_list.append(pool.apply_async(processing,(page_url,)))n pool.close()n pool.join()n player_list=[result.get() for result in player_list]n uni_mdetext=.join([p.umdtext for p in player_list])#全集的md文本n with codecs.open(./uni_data.md,w,encoding=utf-8) as f:n f.write(uni_mdetext)n htmltext=<meta http-equiv="content-type" content="text/html; charset=UTF-8"> r+markdown.markdown(uni_mdetext)n with codecs.open(./uni_data.html,mode=w,encoding=utf-8) as f:n f.write(htmltext)n with open(./players.pkl,wb) as f:#保存運動員player對象的列表n pickle.dump(player_list,f)n

運行結果如圖:

我們用瀏覽器打開HTML文件

右鍵列印

Done!至此我們完成了對崑崙決所有自由搏擊選手公開信息的抓取,並生成了一個專屬的「機密檔案」pdf文件!

我們把每個player都dump起來,留待以後進一步的統計分析。

成品:

鏈接:pan.baidu.com/s/1gfHwMh 密碼:btk6

淺談搏擊運動中的體育數據分析(吐槽)

恕我直言,搏擊運動簡直是數據分析的荒漠,幾乎停留在「老中醫看病」的經驗主義階段。

  1. 信息不公開。
  • 崑崙決號稱引入數據統計,但是數據從未公布崑崙決引入技術統計 保證賽事公平公正公開數據說話我的本意是抓一些技術統計數據的,結果只能抓一些簡介。同樣,在國內外我都沒有中的搏擊方面的數據集。

  • 相關研究較少。
    • 沒信息、沒數據,怎麼研究?

    我相信很多人都看過《點球成金》這部電影,能夠理解基於數據統計的方法能給一項運動帶來多大的改變。沒看過的希望去看一看,特別是從業者。

    與搏擊不同,足球和籃球的技術體育數據分析非常發達,數據也很開放、容易獲得。甚至可以基於統計數據做量化博彩交易策略。

    這是我前幾天看過的一篇散打運動的paper,它通過數據分析的方法研究了散打運動員鞭腿運用情況。李大龍, 李小龍. 我國高水平散打運動員鞭腿技術運用特點分析[J]. 遼寧體育科技, 2015(4):105-107.

    它統計了十二屆全運會上高水平散打運動員鞭腿的運用情況

    這樣的數據統計難道對於運動員沒有指導意義嗎?這樣的研究就不能更多一點嗎?

    老說誰誰誰鞭腿厲害,誰誰誰拳很重.....

    應該拿出數據來,誰誰誰的鞭腿運用率是多少成功率是多少,再研究科學、準確的對策。

    誠然,客觀上搏擊運動動作更迅速,情況更複雜,技術統計有一定難度,但是這些困難不是很難克服的,主要還是看有沒有心去做。

    希望中國的搏擊運動發展的越來越好!

    ps:請各位自覺維護知乎的網路環境。上次寫個技術分享博客被噴子撕了半天,這次說好了,批評可以,請指出具體的技術上的不足。再有瞎噴的我也不和你用鍵盤撕了,直接在北京切磋一下搏擊吧,散打規則,時間地點你定:-D

    推薦閱讀:

    Python數據分析模塊 | pandas做數據分析(一):基本數據對象
    使用Python進行語音識別---將音頻轉為文字
    Python-Excel 模塊哪家強?
    從零開始掌握Python機器學習:十四步教程

    TAG:搏击项目 | 爬虫 | Python |