Python

pandasでwebページの表をスクレイピングする方法

By 2022年4月10日No Comments

pandasを使うことで、webページの表を簡単にスクレイピングすることができます。

スクレイピングについて、そのやり方について具体例を挙げて解説していきます。様々な分析において便利な機能なのでぜひ使えるようになりましょう。

Udemyの動画学習でもPythonを勉強しよう!

「平日の夜の勉強会には時間が間に合わなくて参加できない」「通勤時間のわずかな隙間時間を勉強時間にあてたい」「本ではよく分からないところを動画で理解を深めたい」そんなあなたはUdemyの動画学習がお勧めです!

UdemyのPythonおすすめ33講座レビューリスト

スクレイピングとは

スクレイピングとは、webに公開されている情報の中から特定の情報を抽出する方法のことを意味しています。特にweb上からデータを取得することをwebスクレイピングといいます。webから収集した情報を新たな情報として生成することで、収集にかかる時間を大きく削減することができます。

準備

データ取得にはpandasのread_html()を用います。read_html()を使うには、webスクレイピング用のライブラリであるbeautifulsoup4, lxml, html5libをインストールしておく必要があります。今回はcondaを利用してインストールしました。コマンドは以下のとおりです。

conda install beautifulsoup4 lxml html5lib

また、最初にpandasのインポートをしておきましょう。

import pandas as pd

read_html()の基本的な使い方

準備ができたので、read_html()の基本的な使い方を解説していきます。read_html()の記述方法は以下のとおりです。

pd.read_html(URL, header, index_col, skiprows)

URL: 読み込みたい対象のURLを記述します。

header: headerに指定したい行を記述します。省略可。

index_col: indexに指定する列を記述します。省略可。

skiprows: 読み飛ばす行数を記述します。省略可。

webスクレイピングの具体的な例

それではここから実際にwebスクレイピングをしてみましょう。今回は2021年度セントラル・リーグの個人打撃成績(https://npb.jp/bis/2021/stats/bat_c.html)を取得してみます。まず、今回読み込むURLを変数URLに格納します。read_html()の引数にURLを指定します。

URL = 'https://npb.jp/bis/2021/stats/bat_c.html'
data = pd.read_html(URL)

中身は以下のようになっています。

print(data)
# [                            0   ...                          24
# 0   規定打席 :チーム試合数×3.1 (端数は四捨五入)  ...  規定打席 :チーム試合数×3.1(端数は四捨五入)
# 1                          順 位  ...                         出塁率
# 2                            1  ...                        .433
# 3                            2  ...                        .390
# 4                            3  ...                        .356
# 5                            4  ...                        .354
# 6                            5  ...                        .369
# 7                            6  ...                        .376
# 8                            7  ...                        .353
# 9                            8  ...                        .320
# 10                           9  ...                        .345
# 11                          10  ...                        .335
# 12                          10  ...                        .347
# 13                          12  ...                        .360
# 14                          13  ...                        .357
# 15                          14  ...                        .408
# 16                          15  ...                        .333
# 17                          16  ...                        .333
# 18                          17  ...                        .333
# 19                          18  ...                        .321
# 20                          19  ...                        .370
# 21                          20  ...                        .359
# 22                          21  ...                        .365
# 23                          22  ...                        .341
# 24                          23  ...                        .313
# 25                          24  ...                        .315
# 26                          25  ...                        .293
# 27                          26  ...                        .367
# 28                          26  ...                        .335
# 29                          28  ...                        .302
# 30                          29  ...                        .328
# 31                          30  ...                        .284
# 32                          31  ...                        .302
# 33                          32  ...                        .303

# [34 rows x 25 columns],
#                                0              1
# 0  セ・リーグ || 個人打撃 | 個人投手 | 個人守備 |  >> パ・リーグ 打撃成績]

dataはリスト構造になっていて、長さは以下のとおりです。

print(len(data))
# 2

今回のwebページでは複数のテーブルがあり、1つ目のテーブルは[0]、 2つ目のテーブルは[1]で確認することができます。今回扱うデータは1つ目のデータ(data[0])になります。head()を使ってdata[0]の最初の5行のデータを見てみましょう。

print(data[0].head())
#                            0   ...                          24
# 0  規定打席 :チーム試合数×3.1 (端数は四捨五入)  ...  規定打席 :チーム試合数×3.1 (端数は四捨五入)
# 1                         順 位  ...                         出塁率
# 2                           1  ...                        .433
# 3                           2  ...                        .390
# 4                           3  ...                        .356

まず、先頭の行に不必要な情報が入っているためskiprow=2として読み飛ばす行を指定します。また、columnsを更新することでより見やすくしてみましょう。

data = pd.read_html(URL, skiprows=2)
print(data[0].head())
#    順位     選手  チーム     打率   試合   打席  ...  故意四  死球  三振  併殺打    長打率    出塁率
# 0   1  鈴木 誠也  (広)  0.317  132  533  ...   11   6  88    7  0.639  0.433
# 1   2  坂倉 将吾  (広)  0.315  132  484  ...    1   4  60    9  0.467  0.390
# 2   3   牧 秀悟  (デ)  0.314  137  523  ...    1   6  85   16  0.534  0.356
# 3   4  近本 光司  (神)  0.313  140  612  ...    0   4  58    6  0.441  0.354
# 4   5  桑原 将志  (デ)  0.310  135  571  ...    1   4  75   12  0.474  0.369

dataから選手と出塁率のみを表示してみます。

print(data[0][['選手', '長打率']].head())
#       選手    長打率
# 0  鈴木 誠也  0.639
# 1  坂倉 将吾  0.467
# 2   牧 秀悟  0.534
# 3  近本 光司  0.441
# 4  桑原 将志  0.474

最初のデータでは打率順に並んでいましたが、長打率順にソートしてみましょう。そのためにまずはlistからDataFrameに変換します。

dataframe = pd.DataFrame(data[0])
print(dataframe.head())
#    順位     選手  チーム     打率   試合   打席  ...  故意四  死球  三振  併殺打    長打率    出塁率
# 0   1  鈴木 誠也  (広)  0.317  132  533  ...   11   6  88    7  0.639  0.433
# 1   2  坂倉 将吾  (広)  0.315  132  484  ...    1   4  60    9  0.467  0.390
# 2   3   牧 秀悟  (デ)  0.314  137  523  ...    1   6  85   16  0.534  0.356
# 3   4  近本 光司  (神)  0.313  140  612  ...    0   4  58    6  0.441  0.354
# 4   5  桑原 将志  (デ)  0.310  135  571  ...    1   4  75   12  0.474  0.369
print(type(dataframe))
# <class 'pandas.core.frame.DataFrame'>

ソートにはsort_values()メソッドを使います。ソートしたい列のラベルを引数に指定します。

dataframe_sort = dataframe.sort_values('長打率')
print(dataframe_sort)
#     順位      選手  チーム     打率   試合   打席  ...  故意四  死球   三振  併殺打    長打率    出塁率
# 31  32  梅野 隆太郎  (神)  0.225  130  458  ...    3   5  107   14  0.300  0.303
# 27  28   京田 陽太  (中)  0.257  113  448  ...    0   7   75    5  0.315  0.302
# 17  18   中野 拓夢  (神)  0.273  135  525  ...    5   6   81    6  0.328  0.321
# 23  24   高橋 周平  (中)  0.259  137  520  ...    4   1   79   21  0.347  0.315
# 8    9   大島 洋平  (中)  0.292  141  596  ...    5   3   60    4  0.350  0.345

デフォルトでは昇順になっているため、引数ascendingをFalseにすることで降順にします。

dataframe_sort = dataframe.sort_values('長打率', ascending=)
print(dataframe_sort.head())
#     順位     選手  チーム     打率   試合   打席  ...  故意四  死球   三振  併殺打    長打率    出塁率
# 0    1  鈴木 誠也  (広)  0.317  132  533  ...   11   6   88    7  0.639  0.433
# 13  14  村上 宗隆  (ヤ)  0.278  143  615  ...    6   6  133   12  0.566  0.408
# 2    3   牧 秀悟  (デ)  0.314  137  523  ...    1   6   85   16  0.534  0.356
# 21  22  岡本 和真  (巨)  0.265  143  592  ...    4   7  108   16  0.530  0.341
# 18  19  山田 哲人  (ヤ)  0.272  137  581  ...    0   5  100   10  0.515  0.370

まとめ

今回はpythonのpandasを利用したwebスクレイピングの方法を解説しました。webスクレイピングができるようになることで、業務の自動化や手間を省くことに繋がるのでぜひ使ってみてください。

Udemyの動画学習でもPythonを勉強しよう!

「平日の夜の勉強会には時間が間に合わなくて参加できない」「通勤時間のわずかな隙間時間を勉強時間にあてたい」「本ではよく分からないところを動画で理解を深めたい」そんなあなたはUdemyの動画学習がお勧めです!

UdemyのPythonおすすめ33講座レビューリスト
HOSL

Author HOSL

More posts by HOSL