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

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

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

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

Python

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

Q&A

解決済

1回答

5867閲覧

python2.7,beautifulsoupでのスクレイピングが、うまく出来ません。

akakage13

総合スコア89

Python 2.7

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

Python

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

0グッド

0クリップ

投稿2016/08/17 10:24

###前提・実現したいこと
python初心者でございます。
競走馬の情報をスクレイピングしておりますが、父馬、母馬の抽出がうまく出来ません。

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

Traceback (most recent call last): File "C:\Users\satoru\horse\horse-test-kami-1.py", line 46, in <module> tdh = tr_arr1.findAll("td") #縺薙%縺ョ謚ス蜃コ譁ケ豕輔↓闍ヲ諷ョ縺励※縺翫j縺セ縺・ AttributeError: 'list' object has no attribute 'findAll'

###該当のソースコード

# -*- coding:utf-8 -*- import urllib2 import codecs import time from bs4 import BeautifulSoup f = codecs.open('horse.csv', 'w', 'utf-8') f.write('horse_name,f_horse_name,m_horse_name,race_date,kaisai,weather,race_number,race_name,tousuu,frame_number,horse_number,horse_odds,popularity,horse_arrival,jockey_name,weight,distance,baba,race_time,difference,horse_pass,pace,nobori,horse_weight,win_horse'+u"\n") url='http://db.netkeiba.com/horse/1994103997/' 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") race_date=tds[0].a.text #日付 kaisai=tds[1].a.text #開催 weather=tds[2].text #天気 race_number=tds[3].text #R race_name=tds[4].a.text #レース名 tousuu=tds[6].text #頭数 frame_number=tds[7].text #枠番 horse_number=tds[8].text #馬番 horse_odds=tds[9].text #オッズ popularity=tds[10].text #人気 horse_arrival=tds[11].text #着順 jockey_name=tds[12].a.text #騎手名 weight=tds[13].text #斤量 distance=tds[14].text #距離 baba=tds[15].text #馬場 race_time=tds[17].text #タイム difference=tds[18].text #着差 horse_pass=tds[20].text #通過 pace=tds[21].text #ペース nobori=tds[22].text #上り horse_weight=tds[23].text #馬体重 win_horse=tds[26].text horse_name_tag=soup.find('div',{'class':'horse_title'}).find('h1') horse_name="".join([x for x in horse_name_tag.text if not x == u'\xa0' and not x == u'\n']) tr_arr1 = soup.select("table.blood_table > tbody > tr") tdh = tr_arr1.findAll("td") #ここの抽出方法に苦慮しております f_horse_name = tdh[0].a.text m_horse_name = tdh[1].a.text print horse_name.strip(),f_horse_name.strip(),m_horse_name.strip(),race_date.strip(),kaisai.strip(),weather.strip(),race_name.strip(),tousuu.strip(),frame_number.strip(),horse_number.strip(),horse_odds.strip(),popularity.strip(),horse_arrival.strip(),jockey_name.strip(),weight.strip(),distance.strip(),baba.strip(),race_time.strip(),difference.strip(),horse_pass.strip(),pace.strip(),nobori.strip(),horse_weight.strip(),win_horse.strip() cols = [horse_name,f_horse_name,m_horse_name,race_date,kaisai,weather,race_number,race_name,tousuu,frame_number,horse_number,horse_odds,popularity,horse_arrival,jockey_name,weight,distance,baba,race_time,difference,horse_pass,pace,nobori,horse_weight,win_horse] f.write(",".join(cols) + "\n") f.close()

###試したこと
soup.find,soup selectを用いて試みましたが、うまくできませんでした。

###補足情報(言語/FW/ツール等のバージョンなど)
f_horse_name:父馬(サンデーサイレンス)、m_horse_name:母馬(ワキア)を抽出することが目的でございます。よろしく御教示お願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

soup.select()をしてからわざわざfindAll()をするのは意味がありません。
全部soup.select()でやってしまえば良い話です。
https://teratail.com/questions/43942soup.select()の意味を少しだけ説明しています(冒頭の箇所)ので読み返してみて下さい。

それと、血統情報のテーブルには<tbody>が無いので、それがあると正しくデータが取れないはずです。
ちゃんとHTMLソースを見て確認しましょう。

soup.select()した結果は、printしてどんな結果が取れたのか確認してください。
今回の場合ならtr_arr1printしてみて下さい。
[ ]で囲まれているとしたら、それはlist型です。findAll()tag型のメソッドでlist型のメソッドでは無いです。

...

あと、エラーとは関係ないですが、
血統情報のテーブルはは競走成績とは別のテーブルですよね?なので競争成績のループの中で取得するのは無駄があります。
以前の騎手のときと同じようにループの前で取得するようにしましょう。

投稿2016/08/17 13:19

argius

総合スコア9388

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

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

akakage13

2016/08/18 12:00

argius様、いつもありがとうございます。 今回、抽出したい部分は以下のHTMLソース部分の、サンデーサイレンスという文字と ワキアという文字の2つでございます。 blood_tableを大枠に考えて、<tbody><tr>から<a>の取得を思いましたが、うまくできません。 1案 tr_arr1 = soup.select("table.blood_table > tbody > tr") 2案 tr_arr1 = soup.findAll('div',{'class':'db_prof_box'}).find('?') #?:見当もつかない意 HTMLソースの根本的な見方が分かっていないことが原因とも思います。 現状では、1案、2案のどちらが良いのかもわかりません。 御教示のいただいた前回の質問の部分も読み返しましたが、ピンときません。 乱文であり、恐縮ではございますが、ヒントをいただけますとありがたく思います。 よろしくお願いいたします。 http://db.netkeiba.com/horse/1994103997/  より抽出を試みております。 抽出対象ソース <div class="db_prof_box"> <dl class="fc"> <dt class="DB_ProfHead_dt_01"> <div class="fc"> <p class="db_prof_top_padigree_title png_bg">血統</p> </div> </dt> <dd class="DB_ProfHead_dd_01"> <table cellpadding="0" cellspacing="0" summary="サイレンススズカの血統表" class="blood_table"> <tbody><tr> <td rowspan="2" class="b_ml"> <a href="/horse/ped/000a00033a/" title="サンデーサイレンス">サンデーサイレンス</a> </td> <td class="b_ml"> <a href="/horse/ped/000a0012bf/">Halo</a> </td> </tr> <tr> <td class="b_fml"> <a href="/horse/ped/000a008c1e/">Wishing Well</a> </td> </tr> <tr> <td rowspan="2" class="b_fml"> <a href="/horse/ped/000a006378/">ワキア</a> </td> <td class="b_ml"> <a href="/horse/ped/000a0017b0/">Miswaki</a> </td> </tr> <tr> <td class="b_fml"> <a href="/horse/ped/000a00930c/">Rascal Rascal</a> </td> </tr> </tbody></table> </dd> </dl> <p class="detail_link"><a href="/horse/ped/1994103997/" title="サイレンススズカの血統詳細">血統詳細・兄弟馬</a></p> </div>
argius

2016/08/18 12:59

私が見る限りでは、当該ページの当該箇所には、<tbody>がありません。 試しに、 table_arr = soup.select("table.blood_table") print table_arr としてみてください。 その中に<tbody>はありますか?
akakage13

2016/08/19 10:35

argius様、ありがとうございました。[]listの意味がよくわかり問題解決いたしました。 ヒントを頂いたおかげで、自力でargius様の御指摘がわかり、少し自信がつきました。 ただ、ひとつ、疑問が残ることがございます。 上記の御指導の中で table_arr = soup.select("table.blood_table") print table_arr としてみてください。 その中に<tbody>はありますか? について、早速、試してはみましたが、確かに<tbody>はございませんでした。 しかしながら、小生は、下記のソースコードから、<tbody>は必ず在ると確信して スクリプトを書いておりました。 <tbody><tr> <td rowspan="2" class="b_ml"> <a href="/horse/ped/000a00033a/" title="サンデーサイレンス">サンデーサイレンス 貴殿の御指導とおり、printしましたら、下記の通りでした。 C:\Users\satoru\horse>horse-test-kami-1-1.py [<td class="b_ml" rowspan="2">\n<a href="/horse/ped/000a00033a/" title="\u30b5\u30f3\u30c7\u30fc\u30 b5\u30a4\u30ec\u30f3\u30b9">\u30b5\u30f3\u30c7\u30fc\u30b5\u30a4\u30ec\u30f3\u30b9</a>\n</td>, <td c lass="b_ml">\n<a href="/horse/ped/000a0012bf/">Halo</a>\n</td>, <td class="b_fml">\n<a href="/horse/ ped/000a008c1e/">Wishing Well</a>\n</td>, <td class="b_fml" rowspan="2">\n<a href="/horse/ped/000a00 6378/">\u30ef\u30ad\u30a2</a>\n</td>, <td class="b_ml">\n<a href="/horse/ped/000a0017b0/">Miswaki</a >\n</td>, <td class="b_fml">\n<a href="/horse/ped/000a00930c/">Rascal Rascal</a>\n</td>] リスト型であることが分かったことと、確かにどこにも<tbody>はございませんでした。 しかしながら、google-Chromeのビューアーで検証にしてツリー構造を確認しましたら <tbody>は確かにありました(上記のソースコードの通り) 大枠の"table.blood_table"が分かった時点で、 printして、それを根拠に逆算を今回はいたしまして、無事に取得することが出来ましたが、次回からは、正直なところ、ツリー構造を読む自信がなくなりました。 小生のツリー構造の見方の何が誤っているのか、御教示頂けますと、幸いでございます。 とにもかくにも、教育まで見据えた御教示に、感謝いたします。 重ねてありがとうございました。 今後とも御指導、よろしくお願いいたします。
argius

2016/08/19 11:02

なるほど、デベロッパーツールのツリービューで見ているんですね。 ツリービューだと、構造が補完されてしまうみたいです。 私も確認してみましたが、確かにtbodyが出てきました。 デベロッパーツールのElementsタブでなく、Sourcesタブで見るか、 ページを右クリックして「ページのソースを表示」をすれば、 生のHTMLソースが見られます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問