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

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

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

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Q&A

解決済

3回答

3190閲覧

pythonとBeautifulsoupで競馬情報をスクレイピングする中で、特定の馬のコードにおいて、途中で、不安定なランダムなエラーが出てしまい、苦慮しております!

akakage13

総合スコア89

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

0グッド

0クリップ

投稿2017/06/03 00:09

netkeiba.com様からpythonとBeautifulsoupで競馬情報をスクレイピングする中で、特定の馬のコードにおいて、途中でエラーが出てしまい、苦慮しております!

# -*- coding:utf-8 -*- import urllib2 import codecs import time from bs4 import BeautifulSoup f = codecs.open('horse1.csv', 'w',encoding='CP932', errors='replace') url='http://db.netkeiba.com/horse/2007100135/' soup = BeautifulSoup(urllib2.urlopen(url).read(),"lxml") tr_arr = soup.select("table.db_h_race_results > tbody > tr") for tr in tr_arr: time.sleep(1) tds=tr.findAll("td") nobori=tds[22].text #上り print nobori.strip() cols = [nobori] f.write(",".join(cols) + "\n")

上記のソースコードを動かしてみますと、以下のような結果になります。

Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\Users\satoru>cd horse C:\Users\satoru\horse>cd horse C:\Users\satoru\horse\horse>horse-scan_s.py 41.5 392(-4) Traceback (most recent call last): File "C:\Users\satoru\horse\horse\horse-scan_s.py", line 19, in <module> nobori=tds[22].text #荳翫j IndexError: list index out of range C:\Users\satoru\horse\horse>horse-scan_s.py C:\Users\satoru\horse\horse>horse-scan_s.py C:\Users\satoru\horse\horse>horse-scan_s.py 41.5 Traceback (most recent call last): File "C:\Users\satoru\horse\horse\horse-scan_s.py", line 19, in <module> nobori=tds[22].text #荳翫j IndexError: list index out of range C:\Users\satoru\horse\horse>horse-scan_s.py C:\Users\satoru\horse\horse>horse-scan_s.py 41.5 40.9 42.9 43.1 42.5 37.5 41.0 40.7 42.6 Traceback (most recent call last): File "C:\Users\satoru\horse\horse\horse-scan_s.py", line 19, in <module> nobori=tds[22].text #荳翫j IndexError: list index out of range C:\Users\satoru\horse\horse>

ご覧のように、毎回、アクセスするたびに、違う答えが返ってきます

http://db.netkeiba.com/horse/2007100135/

スイセンキョウという、お馬さんです。

かたや、他のお馬で同じ事を行ってみます

# -*- coding:utf-8 -*- import urllib2 import codecs import time from bs4 import BeautifulSoup f = codecs.open('horse1.csv', 'w',encoding='CP932', errors='replace') url='http://db.netkeiba.com/horse/2010100483/' soup = BeautifulSoup(urllib2.urlopen(url).read(),"lxml") tr_arr = soup.select("table.db_h_race_results > tbody > tr") for tr in tr_arr: time.sleep(1) tds=tr.findAll("td") nobori=tds[22].text #上り print nobori.strip() cols = [nobori] f.write(",".join(cols) + "\n") f.close()

http://db.netkeiba.com/horse/2010100483/
トーキングドラムというお馬さんです

C:\Users\satoru\horse\horse>horse-scan_s.py 34.5 34.7 35.3 35.2 35.4 36.1 34.3 34.5 33.9 34.2 35.3 33.7 33.8 33.2 34.7 34.1 34.1 35.8 34.1 35.6 37.3 38.7 37.9 C:\Users\satoru\horse\horse>

このように、順調にデータをスクレイピングすることが出来ます。

この、スイセンキョウという馬の何が問題なのか、御教示いただければ幸いに思います。

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

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

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

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

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

guest

回答3

0

# -*- 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()

上記のスクリプトの4行目から25行目までの内容は、他のサイトで調べたものを、貼り付けただけのものでございますので、理解はいたしておりません。ただ、tmp様から御指摘いただきました、西森将司さんの御名前は、文字化けしなかったので、良しといたしました。尚、なぜ、netkeiba.com様のサイトが、euc-jpを使っていることが分かるのかについては、少し調べましたが、確実な見分け方などないという意見が多いように思いました。

投稿2017/06/03 23:51

akakage13

総合スコア89

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

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

0

自己解決

# -*- 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()

4行目から25行目のスクリプトは、他のサイトで調べたものを貼り付けたものでございます。

これが、正しく動いているのかは分かりませんが、tmp様の、御教示の西森騎手が原因と思われる漢字コードの

問題は解決致しました。西森将司さんのお名前はプリント出来ました。

後、御教示の中にございました、『読み込むサイトは、euc-jpを使用しています。』

について、なぜ、euc-jpを使用しているのが、判別出来るかについては、少し調べたのですが、

確実な見分け方はないとのことで、理解いたしました。

投稿2017/06/03 23:41

akakage13

総合スコア89

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

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

0

読み込むサイトは、euc-jpを使用しています。
漢字コードの変換をしてからBeautifulSoupに渡してはどうでしょうか?

漢字コードの違いで、騎手名などが">"などに変換されてBeautifulSoupが正しく判断できないと思っています。

(euc-jpの「西」(C0 BE)の字がutf-8として読み3Eの">"として扱ってしまう。騎手 西森将司さんが犯人だ!)

投稿2017/06/03 03:39

tmp

総合スコア277

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

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

akakage13

2017/06/03 09:28

tmp様、御回答ありがとうございます。 早速、小生の出来る範囲でソースコード改変して見ましたが、うまく動きませんでした。 恐縮ではございますが、euc-jpを用いた、漢字コードの変換をしてからBeautifulSoupに渡す ソースコードを、御教示いただけませんでしょうか。 よろしくお願いいたします。 以下が、小生が作成した、動かないソースコードでございます。 # -*- 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; from bs4 import BeautifulSoup f = codecs.open('horse1.csv', 'w','utf-8') url='http://db.netkeiba.com/horse/2007100135/' soup = BeautifulSoup(urllib2.urlopen(url).read(),"lxml") tr_arr = soup.select("table.db_h_race_results > tbody > tr") for tr in tr_arr: time.sleep(1) tds=tr.findAll("td") nobori=tds[22].text #上り print nobori.strip() cols = [nobori] f.write(",".join(cols) + "\n") f.close()
akakage13

2017/06/03 23:31

tmp様、なんとか、漢字コードの変換は下記のスクリプトで改善されたと思っています。 御教示、ありがとうございました、 今後とも、よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問