這幾天想搞到一個三階魔方排行榜的數據,官網居然不能導出Excel文件,剛好這幾天學了個爬蟲,於是爬著玩玩(應該不會進去)。 1 目標網站: https://www.worldcubeassociation.org/results/rankings/333/average 2 準備庫 ## 準備的庫 ...
這幾天想搞到一個三階魔方排行榜的數據,官網居然不能導出Excel文件,剛好這幾天學了個爬蟲,於是爬著玩玩(應該不會進去)。
1 目標網站:
https://www.worldcubeassociation.org/results/rankings/333/average
2 準備庫
## 準備的庫
import pandas as pd # 數據分析庫
import requests # 用於發送 HTTP 請求
from lxml import etree # 可以將xml格式的文件轉為樹狀結構
3 申請訪問
如下圖:點擊 “網路” => “文檔” => “average”
點擊預覽,就能看到排行榜的數據信息. 我們要爬的數據就在這裡
點擊“標頭”,獲取 url 和 標頭
## 標頭
headers = 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)'
## 訪問地址
url = 'https://www.worldcubeassociation.org/results/rankings/333/average'
r = requests.get(url,headers)
# r.text xml格式 又臭又長就不展示了
data_ml = etree.HTML(r.text) #轉成樹狀結構
3 尋找規律
接下來就是無聊的尋找環節,點擊“元素”
經過不懈的努力,終於看到了 Tymon 的大名,意味著我找到了排行榜的數據。。接下來的工作就輕鬆了
3.1 獲取選手排名列表
(話說排行榜的rank不就是1-100的自然數序列麽,其實只要 range(1,101) 就行。。)
先看下世界第一 Tymon 的世界排名。。
在目標位置右擊,賦值完整的XPath
data_ml.xpath('/html/body/main/div[3]/div[2]/div/div/table/tbody/tr[1]/td[1]/text()')[0] #第一位選手的排名
[out]: '1'
這說明世界第一的Tymon的世界排名是1,太棒了完全吻合
再看看世界第二的 MaxPark,同樣的賦值 XPath 信息
data_ml.xpath('/html/body/main/div[3]/div[2]/div/div/table/tbody/tr[2]/td[1]/text()')[0] #第二位選手的排名
[out]: '2'
又完美匹配,同時找到規律,tr[k]
就是第k名選手的信息。按照這個規律我們可以得到前100名選手的排名序列:
## 爬取前一百名選手的排名序列
rank_cuber = []
for i in range(100):
rank_cuber.append(
int(data_ml.xpath('/html/body/main/div[3]/div[2]/div/div/table/tbody/tr'+'['+str(i+1) + ']'+'/td[1]/text()')[0])
)
# rank_cuber
3.2 獲取選手姓名列表
有了上一個試驗,下麵就得心應手了。同樣地,我們先看下世界排名第一Tymon的姓名
data_ml.xpath('/html/body/main/div[3]/div[2]/div/div/table/tbody/tr[1]/td[2]/a/text()') #第一位選手的姓名
[out]: ['Tymon Kolasiński']
完美吻合,下麵只需改tr[k]
就能知道第k名選手的姓名了。不妨試驗一下,中國第一的許瑞航的世界排名是4,我們嘗試爬取第4名選手的姓名信息
data_ml.xpath('/html/body/main/div[3]/div[2]/div/div/table/tbody/tr[4]/td[2]/a/text()') #第一位選手的姓名
[out]: ['Ruihang Xu (許瑞航)']
完全正確,下麵寫個迴圈爬取前100名選手的姓名
name_cuber = []
for i in range(100):
name_cuber.append(
data_ml.xpath('/html/body/main/div[3]/div[2]/div/div/table/tbody/tr'+'['+str(i+1)+']'+'/td[2]/a/text()')[0]
)
# name_cuber
3.3 爬取選手的國籍
過程和上面完全一樣,直接上代碼
country_cuber = []
for i in range(100):
country_cuber.append(
data_ml.xpath('/html/body/main/div[3]/div[2]/div/div/table/tbody/tr'+'['+str(i+1)+']'+'/td[4]/text()')[1]
)
# country_cuber
3.4 爬取成績
WCA賽事中,選手每一輪都會有五次複原,從而會有五個成績,這五次成績的去尾平均就是該選手本輪比賽的平均成績。下麵我將爬取排名前100名選手的最佳的五次成績和平均成績。
過程也差不多,不多贅述,直接上代碼
solve_cuber = [] # 五次成績
for i in range(100):
l = []
# 取出五次成績
for j in range(5):
l.append(
data_ml.xpath('/html/body/main/div[3]/div[2]/div/div/table/tbody/tr'+'['+str(i+1)+']'+'/td'+'['+str(6+j)+']'+'/text()')[0]
)
solve_cuber.append(l)
# solve_cuber
solve_average_cuber = [] #平均成績
for i in range(100):
solve_average_cuber.append(
data_ml.xpath('/html/body/main/div[3]/div[2]/div/div/table/tbody/tr'+'['+str(i+1)+']'+'/td[3]/text()')[0]
)
# solve_average_cuber
註:DNF說明該選手這把成績因某種原因無效
整合成 excel 文件
# 合成數據框
cuber_data = pd.DataFrame({
'排名' : rank_cuber,
'姓名' : name_cuber,
'國籍' : country_cuber,
'五次成績' : solve_cuber,
'去尾平均' : solve_average_cuber,
})
cuber_data.head()
排名 | 姓名 | 國籍 | 五次成績 | 去尾平均 | |
---|---|---|---|---|---|
0 | 1 | Tymon Kolasiński | Poland | [4.02, 4.68, 5.33, 4.56, 5.59] | 4.86 |
1 | 2 | Max Park | United States | [4.88, 5.70, 5.56, 4.53, 4.80] | 5.08 |
2 | 3 | Matty Hiroto Inaba | United States | [5.23, 4.84, 6.48, 5.68, 4.74] | 5.25 |
3 | 4 | Ruihang Xu (許瑞航) | China | [5.48, 5.52, 5.45, 4.06, 7.51] | 5.48 |
4 | 5 | Feliks Zemdegs | Australia | [7.16, 5.04, 4.67, 6.55, 4.99] | 5.53 |
# 導出為excel文件
cuber_data.to_excel("前100名選手成績.xlsx")