• 締切済み

python,bs4でスクレイピング出来ません

**お世話になります、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を多用して、力ずくで作ったプログラムでございます。 先輩の皆様方、御教示よろしくお願いいたします。

みんなの回答

回答No.1

前回のはミスっていましたので修正しました。 # -*- coding:utf-8 -*- import urllib2 import codecs import cStringIO import csv from bs4 import BeautifulSoup # CSVをUnicodeで保存 class UnicodeWriter: """ A CSV writer which will write rows to CSV file "f", which is encoded in the given encoding. """ def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds): # Redirect output to a queue self.queue = cStringIO.StringIO() self.writer = csv.writer(self.queue, dialect=dialect, **kwds) self.stream = f self.encoder = codecs.getincrementalencoder(encoding)() def writerow(self, row): self.writer.writerow([s.encode("utf-8") for s in row]) # Fetch UTF-8 output from the queue ... data = self.queue.getvalue() data = data.decode("utf-8") # ... and reencode it into the target encoding data = self.encoder.encode(data) # write to the target stream self.stream.write(data) # empty queue self.queue.truncate(0) def writerows(self, rows): for row in rows: self.writerow(row) def cmd(): base_url = 'http://db.netkeiba.com/?pid=jockey_detail&id=00663&page={0}' data = [] for i in xrange(1, 5): url = base_url.format(i) soup = BeautifulSoup(urllib2.urlopen(url).read(), 'html.parser') tr = soup.select('#contents_liquid > table > tbody > tr') td = [[x.get_text().strip() for x in y.select('td')] for y in tr] data.extend(td) # CSV保存 with open('horse.csv', 'wt') as fw: writer = UnicodeWriter(fw) writer.writerows(data) if __name__ == '__main__': cmd()

関連するQ&A

  • pythonでスクレイピングがうまく出来ません

    python2.7でbeautifulsoupを用いて、netkeiba.comから競馬情報(騎手の成績)をスクレイピングしています。 定法に基づきまして、『検証』からページのツリー構造を把握して、プログラムを作成しました。 馬名部分の構造が<td class="txt_l"> <a href="/horse/2011105901">テンテマリ</a></td> #テンテマリは馬名 となっておりましたので、"txt_l"を拾い出せるようにスクリプトを作りました。 しかしながら、 馬名以外の"txt_l"は全部スクレイピング出来るのですが、馬名部分だけがNoneと返ってまいります。 エラーメッセージではありませんが、何が原因でNoneとなるのかが、どうしても分かりません。 ちなみに、馬名以外で、ほぼ同様の構造を持つ、『レース名』、構造は <td class="bml txt_l"> <a href="/race/201603020812/" title="3歳上500万円下">3歳上500万円下</a> (3歳上500万円下はレース名) では、問題なくレース名を拾うことが出来ました。 該当のソースコード -*- coding:utf-8 -*- import urllib2 import codecs from bs4 import BeautifulSoup tpl_url='http://db.netkeiba.com/?pid=jockey_detail&id=00663&page={0}' for i in xrange( 1, 2 ): 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: lrg1 = tr.findAll('td',{'class':'txt_l'}) for tr1 in lrg1: print tr1.string 試したこと 馬名以外の('td',{'class':'txt_l'})に準ずる『レース名』は、うまく拾うことが出来ました。 lrg1 = tr.findAll('td',{'class':'txt_l'}) で馬名を得ることが出来ない理由、併せて馬名を拾えるスクリプトを御教示くださいますよう、よろしくお願いいたします!

  • csvファイルに保存が出来ずに困っています!!

    python初心者でございます。 python2.7,beautifulsoupを用いて競馬情報をスクレイピングしましたが、 作成されたhorse.csvファイルにデータ保存が出来ず、困っております。 csvファイルに保存出来るスクリプトを、御教示よろしくお願いいたします。 小生が作成したソースコード -*- coding:utf-8 -*- import urllib2 import codecs from bs4 import BeautifulSoup f = codecs.open('horse.csv', 'w', 'utf-8') f.write('tr1') tpl_url='http://db.netkeiba.com/?pid=jockey_detail&id=00663&page={0}' for i in xrange( 1, 2 ): 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: lrg1 = tr.findAll('td',{'class':'txt_l'}) for tr1 in lrg1: print tr1.a.string f.close() 試したこと 上記のプログラムを動かすと作成されたCSVファイルには何も記録、保存されておりませんでした。 御教示よろしくお願いいたします!!!

  • pythonでのスクレイピング

    python2.7とBeutifulSoupで特定のHPからHTMLを取ってきて処理するプログラムを作っているのですが、正規表現でちょっと困っています。 soup=BeautifulSoup(HTML) s=soup.findAll("a"[,href=○○○、title=○○○]) でリンク<a>のHTMLを取得でき[]で絞込みが出来ます。さらに○○○には正規表現を使うことが出来ます。私はtilteにAを含まないもの、かつBをも含まないもの。という条件指定をしたいのですが、 正規表現で「もしくは「|」」は見当たるのですが「かつ」がみあたりません。 今は絞込みの後、if:continueを使ってBがあれば処理をパスするようにしていますが他によい方法は無いのでしょうか? beautifulsoupの使い方も合わせて教えていただけるとありがたいです。

  • PHPによるスクレイピングについて。

    amazonでapiを使わず、スクレイピングをしたいと考えています。ソースを取得後、取得ソース中の下記部分を正規表現で抽出したいと考えていますが、実行すると、「Array ( [0] => Array ( ) [1] => Array ( ) )」 と表示されてしまいます。どこに問題がありますでしょうか? <a href="http://www.amazon.co.jp/gp/offer-listing/B000JJRWIU/ref=sr_1_olp_9/377-5056805-4862865?ie=UTF8&s=dvd&qid=1330077227&sr=1-9">9 点の全新品/中古品を見る</a> <span class="otherprice">¥ 1,197</span>より</span></td></tr><tr><td class="pointsEarnable"></td></tr><tr><td class="fastTrackList">通常5~7日以内に発送</td></tr> <tr><td class="srListSSS"><span class="srEmphSSS">通常配送無料</span></td></tr> <?php include( "scrape_func2.php" ); $_rawData = getURL( "http://www.amazon.co.jp/%E6%81%8B %E6%84%9B-%E5%A4%96%E5%9B%BD%E6%98%A0%E7%94%BB- DVD/b/ref=bw_ab_562016_5? ie=UTF8&node=589344&pf_rd_p=106708969&pf_rd_s=left- 1&pf_rd_t=101&pf_rd_i=562016&pf_rd_m=AN1VRQENFRJN5&pf_rd_r=1G XM2TY1R5SDE3MA35XJ" ); $_rawData = mb_convert_encoding($_rawData, "SJIS", "ASCII,JIS,UTF-8,EUC-JP,SJIS"); /*<a href="http://www.amazon.co.jp/gp/offer-listingで始まり、</span></td></tr>で終わる部分を抽出*/ preg_match_all("/(<a href=\"http:\/\/www.amazon.co.jp\/gp\/offer-listing <\/span><\/td><\/tr>)/", $_rawData, $match); print_r($match); ?> scrape_func2.php <?php function getURL( $pURL ) { $_data = null; if( $_http = fopen( $pURL, "r" ) ) { while( !feof( $_http ) ) { $_data .= fgets( $_http,1024 ); } fclose( $_http ); } return( $_data ); } ?>

    • ベストアンサー
    • PHP
  • python スクレイピングでのログインができない

    スクレイピングをするために 下記のようなログインサイトにpythonでログインしたいです。 仮定url ="https://aaaaaaa/signin" <form> <p class="signin-label">ログイン画面</p> <ul class="signin-list"> <li class="signin-item"> <div class="hoge1"> <label class="hoge2">メールアドレス</label><div class="hoge3"> <input id="email" autocomplete="email" class="hoge4" type="email" required=""></div> </div> </li> <li class="signin-item"> <div class="hoge5"> <label class="hoge6">パスワード</label> <div class="hoge7"> <input id="password" autocomplete="new-password" class="hoge8" type="password" required=""></div> </div><p class="txt-right"> <a class="signin-link" href="/d/forgot_password">パスワードをお忘れの方</a></p></li></ul><div class="txt-center"> <button type="submit" class="hoge9">ログイン</button> </div> </form> ★行っているコード import requests from bs4 import BeautifulSoup from urllib.parse import urljoin # メールアドレスとパスワードの指定 MAIL = "aaa@mail.net" PASS = "555" # セッションを開始 session = requests.session() # ログイン login_info = { "email":MAIL, "password":PASS, } # action url_login = "https://aaaaaaa/signin" res = session.post(url_login, data=login_info) res.raise_for_status() # エラーならここで例外を発生させる res.text ※エラー内容 HTTPError: 404 Client Error: Not Found for url:https://aaaaaaa/signin 上記となります。 お知恵拝借いただけないでしょうか。

  • pythonでのスクレイピング、ファイル操作につい

    pythonで特定のHPの<a>タグから、「title」を取ってきて、「title」.txtとというテキストファイルを複数作りたいのですが、エラーが出て困っています。 beautifulsoupを用いて取ってきたタイトル名をファイル名するソースコードです。 links=soup.findAll("a",href=s,title=fuyou) for link in links:  title=link.get("title")  filename=title+".txt"  print filename  f2=open(filename,"w").close() >>> バックパック.txt 寝袋(シュラフ)/マット.txt Traceback (most recent call last): File "C:\Python27\test1.py", line 35, in <module> f2=open(filename,"w").close() IOError: [Errno 2] No such file or directory: u'\u5bdd\u888b\uff08\u30b7\u30e5\u30e9\u30d5\uff09/\u30de\u30c3\u30c8.txt' 上のようなエラーが出ます。途中までTXTファイルは出来るのですが、途中からこのようなエラーが出ます。 さっぱり意味が分かりません。どなたか助けてください。

  • <緊急>テーブルを使わないで作るには?

    お世話になります。 <table width="740" cellspacing="0"> <tr valign="middle"> <td width="367"></td> <td></td> </tr> <tr valign="middle" bgcolor="FFFFCE"> <td>  <a href="A073.htm" target="_parent" class="style132">・ あああ</a></td> <td>  <a href="A017.htm" target="_parent" class="style132">・ いいい</a></td> </tr> <tr valign="middle" bgcolor="FFCCFF"> <td>  <a href="A069.htm" target="_parent" class="style132">・ ううう</a></td> <td>  <a href="A043.htm" target="_parent" class="style132">・ えええ</a></td> </tr> <td></td> </tr> <tr valign="middle"> <td></td> <td></td> </tr> </table> こちらをテーブルタグを使わない形に変更したいと思っています。 どなたかお知恵をお貸しください、よろしくお願いいたします。

    • ベストアンサー
    • HTML
  • スクレイピングPHPにおける複数spanについて

    外部のホームページのソースを拾いRSS化するPHPを作成しました。 ***************************************** 外部ホームページ http://hoge.com/index.html ***************************************** <html> <table class="Table100"> <tr> <th class="Name"><h1>えんどう豆</h1></th> <td class="Price">254</td> <td class="maker"> <span class="a1">メーカー</span> <span class="a2">遠藤農園</span> </td> </tr> </table> </html> ***************************************** スクレイピングPHP http://hagedebu.jp/index.php  ***************************************** <?php class SimpleXMLExtended extends SimpleXMLElement { public function addCData($data) { $dom = dom_import_simplexml($this); $dom->appendChild($dom->ownerDocument->createCDATASection($data)); } } $xml = new SimpleXMLExtended('<rss version="2.0"></rss>'); $channel = $xml->addChild('channel'); $channel->addChild('title', 'TEST RSS'); $dom = new DOMDocument; @$dom->loadHTMLFile('http://hoge.com/index.html'); $xpath = new DOMXPath($dom); foreach ($xpath->query('//*[@class="Table100"]') as $node) { $item = $channel->addChild('item'); $item->addChild('description')->addCData(implode('<br>', [ $xpath->evaluate('string(.//*[@class="Name"]/h1)', $node), $xpath->evaluate('string(.//*[@class="Price"])', $node), $xpath->evaluate('string(.//*[@class="maker"]/span)', $node), ])); } header('Content-Type: application/xml; charset=utf-8'); $xml->asXML('php://output'); ************************************************ 問題点 このPHPでは、 えんどう豆 254 メーカー と表示されてしまいます。 <td class="maker"> <span class="a1">メーカー</span> <span class="a2">遠藤農園</span> </td> class="makerに複数のspanが入っているため、2つめのspanを認識しません。 当方が表示させたいのは下記のようにspanを両方とも表示させたいです。 またはひとつしか表示させることができない場合は、「メーカー」ではなく「遠藤農園」を優先表示させたいです。 このように表示させるためにはどうすればよいでしょうか? 希望表示 えんどう豆 254 メーカー 遠藤農園 または えんどう豆 254 遠藤農園 よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • エクセルファイルを、HTMLに出力

    エクセルファイルを各項目ごとにHTMLに出力したいのですが、 何かよいソフトや方法はないでしょうか? <tr><td class="x_01"><a href="【A1】" target="_blank">【B1】</a></td><td class="y_02">【C1】</td><td class="z_03">【D1】</td></tr> <tr><td class="x_01"><a href="【A2】" target="_blank">【B2】</a></td><td class="y_02">【C2】</td><td class="z_03">【D2】</td></tr> .... このような形式で、出力していきたいです。 とりあえず、このように自動で出力できる方法ならばどのような方法でも構いません。 どうぞよろしくおねがいします。

  • CSS line-height が効かない

    下記のように<table>の行の間隔を狭める為、CSSのline-height: をつかっているのですが、 <td>の内側に<a hrefを使っているのが原因なのか、line-heightが効きません。 sample.css table td.aa { font-size : 0.8em; line-height:150%; } sample.html <table> <tr><td class="aa"><a href="http://......">ああああああああ</a> </td></tr> <tr><td class="aa"><a href="http://......">いいいいいいいい</a> </td></tr> </table> どなたかお助けください。

    • ベストアンサー
    • HTML