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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python

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

Q&A

解決済

1回答

2751閲覧

競馬情報をpython,beautifulsoupでスクレイピングしていますが、IndexError: list index out of range に対応しているのに、うまく動かず、困っています!

akakage13

総合スコア89

Python

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

0グッド

0クリップ

投稿2017/06/04 00:30

netkeiba.com様より、競馬情報をpython,beautifulsoupでスクレイピングしていますが、
IndexError: list index out of range に対応したのに、うまく動かず、困っています!

# -*- coding:utf-8 -*- import urllib2 import codecs import time def tounicode(data): f = lambda d, enc: d.decode(enc); codecs = ['shift-jis','utf-8','euc-jp','cp932', 'euc-jis_2004','euc-jisx0213','iso2022-jp','iso2022-jp-1', 'iso2022-jp-2','iso2022-jp-2004','iso2022-jp-3','iso2022-jp-ext', 'shift-jis-2004','shift-jisx0213','utf-16','utf-16-be', 'utf-16-le','utf-7','utf-8-sig']; for codec in codecs: try: return f(data, codec); except: continue; return None; def toeuc(data): data1 = tounicode(data); # 上で紹介したUnicode変換メソッド data2 = []; for char in data1[:]: # スライスで一文字ずつ調べる try: data2.append(char.encode('euc-jp')); except: pass; return ''.join(data2); import random from bs4 import BeautifulSoup f = codecs.open('h2007_1.csv', 'w', 'utf_8') f.write('horse_name,jockey_name,nobori'+u"\n") horse_name = "" start_url = 'http://db.netkeiba.com/horse/2007100{0}/' for i in xrange(1,1000): url = start_url.format(i) soup = BeautifulSoup(urllib2.urlopen(url).read(), "lxml") time.sleep(random.uniform(5,10)) horse_name_tag = soup.find('div', {'class': 'horse_title'}) if horse_name_tag is not None: if horse_name_tag.find('h1') != None: horse_name = horse_name_tag.find('h1').text horse_name = "".join( [x for x in horse_name_tag.text if not x == u'\xa0' and not x == u'\n']) tr_arr = soup.select("table.db_h_race_results > tbody > tr") for tr in tr_arr: tds=tr.findAll("td") if len( tds ) > 0: jockey_name=tds[12].a.text #騎手名 nobori=tds[22].text #上り print horse_name.strip(),jockey_name.strip(),nobori.strip() cols = [horse_name,jockey_name,nobori] f.write(",".join(cols) + "\n") else: continue f.close()

当サイトの先輩から、netkeiba.comはeuc-jpの漢字コードであると御指摘をいただきましたので、4行目から25行目付近はその対策のために、他のサイト等で調べて貼り付けたものでございます。その目的のために作用しているかは不明ではございますが、上記スクリプトは、途中までは快適に動きます。

以下が、プリント画面でございます。

Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\Users\satoru\horse\horse\2007>t_horse_scan_2007_1.py カントリースノー 2.75抹消 セ 黒鹿毛 草野太郎 13.2 カントリースノー 2.75抹消 セ 黒鹿毛 草野太郎 13.4 カントリースノー 2.75抹消 セ 黒鹿毛 原田和真 カントリースノー 2.75抹消 セ 黒鹿毛 高野和馬 途中、省略 □地スイセンキョウ 0.00 牝 鹿毛 永森大智 40.0 □地スイセンキョウ 0.00 牝 鹿毛 上田将司 43.1 □地スイセンキョウ 0.00 牝 鹿毛 石本純也 41.6 □地スイセンキョウ 0.00 牝 鹿毛 石本純也 42.2 □地スイセンキョウ 0.00 牝 鹿毛 岡村卓弥 40.8 □地スイセンキョウ 0.00 牝 鹿毛 上田将司 44.8 □地スイセンキョウ 0.00 牝 鹿毛 上田将司 42.6 Traceback (most recent call last): File "C:\Users\satoru\horse\horse\2007\t_horse_scan_2007_1.py", line 64, in <module> nobori=tds[22].text #荳翫j IndexError: list index out of range C:\Users\satoru\horse\horse\2007>

IndexError: list index out of range とエラーメッセージが出ましたが、

tr_arr = soup.select("table.db_h_race_results > tbody > tr") for tr in tr_arr: tds=tr.findAll("td") if len( tds ) > 0: jockey_name=tds[12].a.text #騎手名 nobori=tds[22].text #上り

上記のように、if文を用いて、対策を講じているつもりです。

しかし、IndexError: list index out of range が出てきます。

すごく、不思議に思って、その箇所のソースコードを調べてみました。

http://db.netkeiba.com/horse/2007100135/ のページのソースコードにおける、
小生のスクリプトのエラー箇所

□地スイセンキョウ 0.00 牝 鹿毛 上田将司 44.8
□地スイセンキョウ 0.00 牝 鹿毛 上田将司 42.6 付近のソースコードの抜粋です。

&nbsp; </td> <td>5-4-4-9</td> <td>&nbsp;</td> <td class="bml">44.8</td> <td>387(-5)</td> <td class="bml" align="center" nowrap> &nbsp; </td> <td class="bml" nowrap> &nbsp; </td> <td><a href="/horse/2008100733/">サクライーグル</a></td> <td>&nbsp;</td> </tr><tr> <td><a href="/race/list/20120227/">2012/02/27</a></td> <td><a href="/race/sum/54/20120227/">高知</a></td> <td>晴</td> <td class="txt_right">8</td> <td class=""><a href="/race/201254022708/" title="C2ロ">C2ロ</a></td> <td> &nbsp; </td> <td class="txt_right">12</td> <td class="txt_right">2</td> <td class="txt_right">2</td> <td class="txt_right">101.4</td> <td class=" txt_right">8</td> <td class="bml txt_right">7</td> <td> <a href="/jockey/a01ad/" title="上田将司">上田将司</a> </td> <td>54</td> <td>ダ1300</td> <td>重</td> <td class="bml txt_right"> &nbsp; </td> <td class="txt_right">1:31.1</td> <td class="txt_right">3.6</td> <td class="bml txt_right"> &nbsp; </td> <td>7-7-5-7</td> <td>&nbsp;</td> <td class="bml">42.6</td> <td>392(+4)</td> <td class="bml" align="center" nowrap>

小生の見る限りでは、

<td class="bml">44.8</td>

<td class="bml">42.6</td>

に、ついても、 真っ当な数値でありまして、空欄でもなく、if len( tds ) > 0: のエラー対策で十分ではと考えています。

しかし、エラーが出てまいります。

**他の nobori=tds[22].text は うまく数字を出してくれるのに、同じソースコードで

なぜ、この部分だけに、エラーが発生する理由が、分からず苦慮しております。
**
先輩方の御教示、よろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

エラー回避の条件が不十分です。

python

1if len( tds ) > 0:

ではなく、

python

1if len( tds ) > 22 + 1:

とするべきです(22の数値部分はtbsの必須の長さにしてください)。

投稿2017/06/04 12:39

pashango2

総合スコア930

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問