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

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

ただいまの
回答率

90.01%

python2.7,beautifulsoupを用いて、規則性のある20行24列の競馬のデータ表をCSVに書き込むことが出来ずに困っています!!!

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,361

akakage13

score 86

前提・実現したいこと

**お世話になります、python初心者ですpython2.7,beautifulsoupを用いて、競馬データをスクレイピングしておりますが、どうにも困っております。
1行だけはprintすることが出来るのですが、20行をスクレイピングするスクリプトと、併せて、CSVに出力させるスクリプトが分かりません。
**

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

**csvに保存が出来ないこと

20行をまとめてスクレイピングすることが出来ないこと`
**
###該当のソースコード

python2.7

# -*- coding:utf-8 -*-


import urllib2
import codecs
from bs4 import BeautifulSoup

f = codecs.open('horse.csv', 'w', 'utf-8')
f.write('race_date,kaisai,weather,race_number,race_name,tousuu,frame_number,horse_number,single_win_ratio,popularity,horse_arrival,horse_name,weight,distance,baba, race_time,difference,horse_pass,pace,nobori,horse_weight,win_horse,prize_money'+ u"\n")

tpl_url='http://db.netkeiba.com/?pid=jockey_detail&id=00663&page={0}'

for i in xrange(1, 5):
    url=tpl_url.format( i )
    soup = BeautifulSoup(urllib2.urlopen(url).read(),"lxml")
    tr_arr = soup.find('div', {'id':'contents_liquid'}).findAll('tbody')  

    for tr in tr_arr:

      #日付#race_date
        lrg1= tr.findAll('td')[0].string
        #開催#kaisai
        lrg2= tr.findAll('td')[1].string
        #天気#weather
        lrg3= tr.findAll('td')[2].string
        #第○レース#race_number
        lrg4= tr.findAll('td')[3].string
        #レース名#race_name
        lrg5= tr.findAll('td')[4].string
        #映像(この部分、削除したいです)
        lrg6= tr.findAll('td')[5].string
        #頭数#tousuu
        lrg7= tr.findAll('td')[6].string
        #枠番#frame_number
        lrg8= tr.findAll('td')[7].string
        #馬番#horse_number
        lrg9= tr.findAll('td')[8].string
        #単勝#single_win_racio
        lrg10= tr.findAll('td')[9].string
        #人気#popularity
        lrg11= tr.findAll('td')[10].string
        #着順#horse_arrival
        lrg12= tr.findAll('td')[11].string
        #馬名#horse_name
        lrg13= tr.findAll('td',{'class':'txt_l'}) [1]
        #斤量#weight
        lrg14= tr.findAll('td')[13].string
        #距離#distance
        lrg15= tr.findAll('td')[14].string
        #馬場#baba
        lrg16= tr.findAll('td')[15].string
        #タイム#race_time
        lrg17= tr.findAll('td')[16].string
        #着差#difference
        lrg18= tr.findAll('td')[17].string
        #通過#horse_pass
        lrg19= tr.findAll('td')[18].string
        #ペース#pace
        lrg20= tr.findAll('td')[19].string
        #上り#nobori
        lrg21= tr.findAll('td')[20].string
        #馬体重#horse_weight
        lrg22= tr.findAll('td')[21].string
        #勝ち馬#win_horse
        lrg23= tr.findAll('td',{'class':'txt_l'}) [2]
        #賞金#prize_money
        lrg24= tr.findAll('td')[23].string

        print lrg1,lrg2,lrg3,lrg4,lrg5,lrg6,lrg7,lrg8,lrg9,lrg10,\
                  lrg11,lrg12,lrg13.a.string,lrg14,lrg15,lrg16,lrg17,\
                  lrg18,lrg19,lrg20,lrg21,lrg22,lrg23.a.string,lrg24


        f.close()

コード
```

(参考)下記のコードが苦慮しておりますスクレイピング対象のHTMLの
最初の1行部分でございます。
開催日毎に、これが1つのページに、20行、連続してございます。
1行しか捕らえられず、困っております。
<tbody>
<tr class="">
<td><a href="/race/list/20160807/">2016/08/07</a></td>
<td><a href="/race/sum/04/20160807/">2新潟4</a></td>
<td>晴</td>
<td class="txt_right">12</td>
<td class="bml txt_l"><a href="/race/201604020412/" title="3歳上500万下">3歳上500万下</a></td>
<td>
<a href="/?pid=movie&amp;id=201604020412" target="_blank"><img src="/style/netkeiba.ja/image/icon_douga.png" border="0"></a>
</td>
<td class="txt_right">15</td>
<td class="txt_right">7</td>
<td class="txt_right">13</td>
<td class="r3ml txt_right">6.9</td>
<td class="r3ml txt_right">3</td>
<td class="r2ml txt_right">2</td>
<td class=" txt_l">
<a href="/horse/2013103614/">チェイスダウン</a>

</td>
<td>54</td>
<td>ダ1200</td>
<td>良</td>
<td class="txt_right">1:11.9</td>
<td class="txt_right">0.3</td>

<td>8-8</td>
<td>34.5-37.1</td>
<td class="r1ml">36.6</td>
<td>468(+2)</td>
<td class=" txt_l">
<a href="/horse/2013101531/">クリムゾンバローズ</a>

</td>
<td>300.0</td>

試したこと

forなどで、ループさせてみましたが、スキル不足でうまくいきませんでした。

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

python2.7

findAllを多用して、力ずくで作ったプログラムでございます。
先輩の皆様方、御教示よろしくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • attakei

    2016/08/10 20:44

    コードの部分をコードブロックで囲んでいただけますか。(``` または エディタの[</>]ボタンで囲めます。詳しくはヘルプを参照してください)

    特にPythonのようにインデントが言語構造上非常に重要な言語は、コードブロックで囲まれている状態でないと正しい状態の把握がしづらくなり、回答が得られにくくなります

    キャンセル

回答 1

checkベストアンサー

0

私の判断ですが、HTMLソースを見たところでは、race_table_01クラスを持ったtableの子のtbodyの子のtrを取得するのが良いと思います。
tr_arr = soup.select("table.race_table_01 > tbody > tr")とすればそのように取得できます。

  • コード例(機能を制限したバージョン)
import urllib2
import codecs
from bs4 import BeautifulSoup

tpl_url='http://db.netkeiba.com/?pid=jockey_detail&id=00663&page={0}'

url = tpl_url.format( 1 ) # とりあえず1ページ目だけ
soup = BeautifulSoup(urllib2.urlopen(url).read(),"lxml")

tr_arr = soup.select("table.race_table_01 > tbody > tr")

for tr in tr_arr:
    tds = tr.findAll("td")
    race_date = tds[0].a.text # 日付
    kaisai = tds[1].a.text # 開催
    print race_date, kaisai

(追記)

CSVファイルのところを書き忘れました。
ざっくり書くと、配列にまとめてjoin関数で結合、ヘッダーと同じくf.write()で出力します。1行出力なので、改行文字をつけます。

# forループの中
    cols = [race_date, kaisai]
    f.write(",".join(cols) + "\n"))

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる
  • トップ
  • 配列に関する質問
  • python2.7,beautifulsoupを用いて、規則性のある20行24列の競馬のデータ表をCSVに書き込むことが出来ずに困っています!!!