見出し画像

F3Asiaの結果をスクレイピングしてcsvにまとめた話

まずコードを載せます

import csv
import urllib
from bs4 import BeautifulSoup
def main():
   list=["QUALIFYING_1","QUALIFYING_2","Race 1","Race 2","Race 3"]
   for item in list:
       url = "https://www.f3asia.com/races/results/2021/ROUND_1/"
       url += item + "/"
       if(item == "Race 3"):
           url = "https://www.f3asia.com/races/results/2021/ROUND%201/races/results/"
       html = urllib.request.urlopen(url)
       soup = BeautifulSoup(html, 'html.parser')
       table = soup.find_all("table")
       for tab in table:
           table_className = tab.get("class")
           if table_className[0] == "table1":
               break
       name = item.replace(' ','_')
       csvname = name + ".csv"
       for tab in table:
           table_className = tab.get("class")
           if table_className[0] == "table1":
               with open(csvname, "w", encoding='utf-8',newline="") as file:
                   writer = csv.writer(file)
                   rows = tab.find_all("tr")
                   for row in rows:   
                       csvRow = []
                       for cell in row.findAll(['td', 'th']):
                           try:
                               element = str(cell.contents[0])
                               csvRow.append(element.replace('/',','))
                           except IndexError:
                               continue
                       del csvRow[2]
                       integration = ','.join(csvRow)
                       degration = integration.split(',')
                       writer.writerow(degration)
               break
if __name__ == "__main__":
   main()

今回F3Asiaの結果を簡単にまとめようと思い,スクレイピングしてcsvに出力しようと思ったけど,意外と大変だったのでまとめます.

1.隠れチーム名

百聞は一見に如かずということで実際のコードを見てもらう

これが予選の表を構成しているコードだ

画像1

対してこれが決勝の表を構成しているコードだ

画像2

おわかりだろうか?レースの表ではspanタグの中にチーム名が隠れているのだ,これを単純にfindAllでtdタグを抜き出しただけだとこのチーム名が出てきて二重に出力されてしまうのだ.

これを回避するために以下のような部分を書き足した

for cell in row.findAll(['td', 'th']):
    try:
        element = str(cell.contents[0])
        csvRow.append(element.replace('/',','))
    except IndexError:
        continue

これによってtdタグと同階層の要素のみを抜き出している

2.URLの命名規則

これは大した問題ではなかったが地味にイライラしたことだ
予選1,2のURLは
https://www.f3asia.com/races/results/2021/ROUND_1/QUALIFYING_1/
https://www.f3asia.com/races/results/2021/ROUND_1/QUALIFYING_2/
決勝のレース1と2のURLは
https://www.f3asia.com/races/results/2021/ROUND_1/Race%201/
https://www.f3asia.com/races/results/2021/ROUND_1/Race%202/
なぜかRaceと数字の間にスペースが入っている
決勝レース3のURLは
https://www.f3asia.com/races/results/2021/ROUND%201/races/results/
もはや3という数字がどこにもない,WHY!!って感じになった

3.ドライバー名とチーム名が分けられていない

画像3

このようにドライバー名とチーム名が同じセルに入っているのだ
違うセルのほうが処理的にも楽だろうに…
これは以下のようにして解決した.


for cell in row.findAll(['td', 'th']):
   try:
       element = str(cell.contents[0])
       csvRow.append(element.replace('/',','))
   except IndexError:
       continue
del csvRow[2]
integration = ','.join(csvRow)
degration = integration.split(',')
writer.writerow(degration)

まず名前とチーム名の間の/(スラッシュ)を,(コンマ)に置換して(replace),次にcsvRowというリストを結合(join)し,それをまたコンマで分離(split)してリスト化することでドライバーとチーム名を別の要素とした(もうちょいいい書き方ないかな…)

このようにして以下のデータを取得した

POS.,CAR,DRIVER,TEAM,LAPS,TIME,GAP,BEST
1,33,Guanyu ZHOU,Abu Dhabi Racing by Prema,19,30:38.0,1:35.922
2,14,Roy NISSANY,Hitech Grand Prix,19,30:44.6,6.997,1:36.428
3,19,Jehan DARUVALA,Mumbai Falcons,19,30:45.2,0.556,1:36.410
4,3,Pierre-Louis CHOVET,Pinnacle Motorsport,19,30:45.5,0.301,1:36.304
5,16,Dino BEGANOVIC,Abu Dhabi Racing by Prema,19,30:46.1,0.655,1:36.182
6,12,Ayumu IWASA,Hitech Grand Prix,19,30:48.5,2.352,1:36.346
7,74,Cem BOLUKBASI,BlackArts Racing,19,30:57.1,8.659,1:36.832
8,6,Isack HADJAR,Evans GP,19,30:57.5,0.371,1:36.324
9,4,Patrik PASMA,Evans GP,19,30:58.3,0.825,1:36.650
10,13,Reece USHIJIMA,Hitech Grand Prix,19,31:01.3,3.001,1:36.898
11,7,Roberto FARIA,Motorscape,19,31:02.0,0.617,1:37.012
12,11,Roman STANEK,Hitech Grand Prix,19,31:03.0,1.039,1:36.776
13,10,Alessio DELEDDA,Pinnacle Motorsport,19,31:04.6,1.604,1:36.643
14,62,Lorenzo FLUXA,BlackArts Racing,19,31:08.8,57:36.rd,1:36.881
15,77,Nicola MARINANGELI,Motorscape,19,31:13.3,4.587,1:37.242
16,88,Amna AL QUBAISI,Abu Dhabi Racing by Prema,19,31:16.2,2.81,1:37.527
17,5,Casper STEVENSON,Evans GP,19,31:19.7,3.522,1:37.485
18,25,Alexandre BARDINON,Pinnacle Motorsport,19,31:38.5,7.8,1:37.621
19,51,Irina SIDORKOVA,Evans GP,19,31:38.5,11.008,1:37.997
20,40,Matthias LUETHEN,Pinnacle Motorsport,19,31:45.7,7.233,1:37.716
21,28,Kush MAINI,Mumbai Falcons,18,31:47.3,1 Lap,1:36.096
DNF,8,Rafael VILLAGOMEZ,BlackArts Racing,1,02:46.9
DNS,66,Zdenek CHOVANEC,BlackArts Racing

この上記の3箇所(特にラスト)でだいぶ頭を悩ませたのでメモ代わりに

参考文献

https://qiita.com/tsnry7913/items/add031f205aaf57fb0ac

この記事が気に入ったらサポートをしてみませんか?