質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1035閲覧

Pythonでのデータスクレイピングでエラーが発生

Ponta2929

総合スコア16

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/02/04 11:08

前提・実現したいこと

プロ野球選手のデータをスクレイピングしたいです。

数日間ググりながらエラーと格闘してコードを修正して見たのですが、全く答えが見つからず
こちらでどなたか助けていただけないかと藁をもすがる思いで書き込ませて頂きました。

下記のページ通りにやってみたのですが、途中でエラーが発生して出来ません。
https://qiita.com/kjybinp1105/items/eeca54b725c27890aa4f

 ※過去の記事なので、URLだけ2019年のものにアップデートしています。

①urlをリスト形式で取得
②URLを入力:2017年だけ命名規則が違う
③データをURLから取得
④選手IDの作成
は、それぞれやると違和感のあるアウトプットはあるものの、エラーは出ずに動作しました(試したことに違和感は記載しました。)

⑤選手IDの付与
で下記のエラーが出てしまい、色々とトライしてもコードを動作させることが出来ませんでした。

発生している問題・エラーメッセージ

--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-60-c862335b2217> in <module> 38 df_all[i]['ID'] = -1 39 for j in range(len(df_all[i])): ---> 40 df_all[i].loc[j,'ID'] = dic[df_all[i].loc[j,'選手名']] 41 df_all[i].index = df_all[i]['ID'] 42 df_all[i] = df_all[i].drop('ID',axis=1) ~/anaconda3/lib/python3.7/site-packages/pandas/core/generic.py in __hash__(self) 1814 def __hash__(self): 1815 raise TypeError('{0!r} objects are mutable, thus they cannot be' -> 1816 ' hashed'.format(self.__class__.__name__)) 1817 1818 def __iter__(self): TypeError: 'Series' objects are mutable, thus they cannot be hashed

該当のソースコード

Python

1import numpy 2import pandas as pd 3import matplotlib.pylab as plt 4 5#①urlをリスト形式で取得 6df_all = []//各要素に各年のデータが入る 7years = range(19,8,-1) 8urls = [] 9 10#②URLを入力:2019年だけ命名規則が違う 11for year in years: 12 if(year==19): 13 urls.append('http://baseball-data.com/stats/pitcher-all/era-1.html') 14 else: 15 urls.append('http://baseball-data.com/'+ "{0:02d}".format(year)+'/stats/pitcher-all/era-1.html') 16 17#③データをURLから取得 18for url in urls: 19 print('取得URL:'+url) 20 df = pd.io.html.read_html(url) 21 df = df[0] 22 df_all.append(df) 23 24#④選手IDの作成 25name_list = [] 26dic = {} 27for i in range(len(df_all)): 28 name_list.extend(df_all[i]['選手名']) 29name_list = list(set(name_list)) 30for i,name in enumerate(name_list): 31 dic[name] = i 32 33#⑤選手IDの付与 34for i in range(len(df_all)): 35 df_all[i]['ID'] = -1 36 for j in range(len(df_all[i])): 37 df_all[i].loc[j,'ID'] = dic[df_all[i].loc[j,'選手名']] 38 df_all[i].index = df_all[i]['ID'] 39 df_all[i] = df_all[i].drop('ID',axis=1) 40 41#⑥index被りを除去 42for i in range(len(df_all)): 43 doubled_index = [] 44 count = df_all[i].index.value_counts() 45 for j in count.index: 46 if(count.loc[j]>1): 47 doubled_index.append(j) 48 df_all[i] = df_all[i].drop(doubled_index) 49 50#⑦カラム名に年を付ける 51for i in range(len(df_all)): 52 for col_name in df_all[i].columns: 53 df_all[i] = df_all[i].rename(columns = {col_name:col_name+"20"+"{0:02d}".format(years[i])}) 54 55df_m = pd.concat(df_all,axis=1)

試したこと

それぞれのステップを順番に動かしたところ①から③は問題なくすることが出来ました。
③の後にdfの中身を見るとなぜか見出しが二重だったところは気になりました。
イメージ説明

④はname_listの中身を見ると、なぜか中身が具体的な選手名ではなく'選手名'という値しか入っていなかったです。
イメージ説明

⑤で下記のエラーが出てスタックしてしまいました。
イメージ説明

補足情報(FW/ツールのバージョンなど)

最新のJupyter Notebookでやっています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2020/02/04 12:01

エラーが出たときの「df_all[i].loc[j,'選手名']」の値はどうなっていますか?
guest

回答1

0

ベストアンサー

とりあえずこれでどうですか?

python

1import pandas as pd 2 3url = 'https://baseball-data.com/stats/pitcher-all/era-1.html' 4df1 = pd.read_html(url, index_col=None, skiprows=0, header=1)[0] 5 6url = 'https://baseball-data.com/18/stats/pitcher-all/era-1.html' 7df2 = pd.read_html(url, index_col=None, skiprows=0, header=1)[0] 8 9url = 'https://baseball-data.com/17/stats/pitcher-all/era-1.html' 10df3 = pd.read_html(url, index_col=None, skiprows=0, header=1)[0] 11 12df1["年"] = 2019 13df2["年"] = 2018 14df3["年"] = 2017 15 16df = pd.concat([df1, df2, df3]) 17 18df.pivot_table(index=["選手名", "チーム"], columns="年")

投稿2020/02/04 12:59

編集2020/02/04 13:08
barobaro

総合スコア1286

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問