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

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

ただいまの
回答率

90.33%

  • Python 3.x

    7369questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

beautiful soup すぐ下の同レベルのタグの取得について

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 144

MitMc

score 23

下記のような構造のhtmlから、各<th>タグの直下の<td>タグを取得したい場合、取得が上手くいかないので教えていただけますでしょうか。下記の方法では出来たのですが、直感的ではないので、thタグのクラスを使って取得したいと考えてます。例えば、単勝のthのすぐ下のtdの2という数字や複勝のthの2番目の下のtdの170という数字を取得したいと考えてます。

取得したいHTMLの構造

<tr>
<th class="tan">単勝</th>
<td>2</td>
<td class="txt_r">450</td>
<td class="txt_r">2</td>
</tr>
<tr>
<th align="center" class="fuku">複勝</th>
<td>2<br/>5<br/>6</td>
<td class="txt_r">170<br/>1,340<br/>310</td>
<td class="txt_r">2<br/>12<br/>6</td>
</tr>
<tr>
<th align="center" class="waku">枠連</th>
<td>1 - 3</td>
<td class="txt_r">1,170</td>
<td class="txt_r">5</td>
</tr>
<tr>
<th align="center" class="uren">馬連</th>
<td>2 - 5</td>
<td class="txt_r">21,850</td>
<td class="txt_r">39</td>
</tr>
</table>

試したこと

上手く行ったやり方

リストの取得

①td_list=html.find_all("td")
②fuku = td_list[0]

上手くいかなかったやり方

上記のような取得の仕方ではなく、
①this_td = html.find("th", class_="fuku")
②fuku = this_td.sibling

のようなやり方でスクレイピングをしたいと思うのですが、エラーになります。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+2

確認しましたが、私の環境では html.find("th", class_='fuku') でも html.find("th", attrs={'class':'fuku'}) も問題なく動作しております。
(下記のサンプル)

ただ、this_td.next_siblings は改行コード\nも一つの要素として取得しているようで、this_td.next_sibling では得られる結果が"\n"となるようです。

個人的には select("th.fuku + td") を使ったほうが簡単に記述できる気がします。

from bs4 import BeautifulSoup
import urllib.request

html_data = """
<tr>
<th class="tan">単勝</th>
<td>
2</td>
<td class="txt_r">450</td>
<td class="txt_r">2</td>
</tr>
<tr>
<th align="center" class="fuku">複勝</th>
<td>2<br/>5<br/>6</td>
<td class="txt_r">170<br/>1,340<br/>310</td>
<td class="txt_r">2<br/>12<br/>6</td>
</tr>
<tr>
<th align="center" class="waku">枠連</th>
<td>1 - 3</td>
<td class="txt_r">1,170</td>
<td class="txt_r">5</td>
</tr>
<tr>
<th align="center" class="uren">馬連</th>
<td>2 - 5</td>
<td class="txt_r">21,850</td>
<td class="txt_r">39</td>
</tr>
</table>
"""

html = BeautifulSoup(html_data, "lxml")

this_td = html.find("th", class_='fuku')
print(list(this_td.next_siblings))
# ['\n', <td>2<br/>5<br/>6</td>, '\n', <td class="txt_r">170<br/>1,340<br/>310</td>, '\n', <td class="txt_r">2<br/>12<br/>6</td>, '\n']

this_td = html.find("th", attrs={'class':'fuku'})
print(list(this_td.next_siblings))
# ['\n', <td>2<br/>5<br/>6</td>, '\n', <td class="txt_r">170<br/>1,340<br/>310</td>, '\n', <td class="txt_r">2<br/>12<br/>6</td>, '\n']

td = html.select("th.fuku + td")
print(td)
# [<td>2<br/>5<br/>6</td>]

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/03 19:22

    ご回答ありがとうございます。
    td = html.select("th.fuku + td")を使用した場合、直下の1番目のtdは取得できるのですが、2番目を取得したい場合にどうしたら良いでしょうか。
    td = html.select("th.fuku + td.txt_r")で取得できると思ったのですが空リストになってしまいました。

    キャンセル

  • 2018/07/03 20:42

    select (cssセレクタ)の場合 '+' は隣接している要素となりますので
    html.select("th.fuku + td + td")
    となるかと思います。

    キャンセル

  • 2018/07/03 21:11

    出来ました。ありがとうございます!

    キャンセル

+1

私なら(この構造が前提として)

this_td = html.find("th", class_="fuku")
td_list = this_td.parent.find_all("td")


でtdのリストを得てから取り出しますね。

>>> from bs4 import BeautifulSoup
>>> html = BeautifulSoup("""<tr>
... <th class="tan">単勝</th>
... <td>2</td>
... <td class="txt_r">450</td>
... <td class="txt_r">2</td>
... </tr>
... <tr>
... <th align="center" class="fuku">複勝</th>
... <td>2<br/>5<br/>6</td>
... <td class="txt_r">170<br/>1,340<br/>310</td>
... <td class="txt_r">2<br/>12<br/>6</td>
... </tr>
... <tr>
... <th align="center" class="waku">枠連</th>
... <td>1 - 3</td>
... <td class="txt_r">1,170</td>
... <td class="txt_r">5</td>
... </tr>
... <tr>
... <th align="center" class="uren">馬連</th>
... <td>2 - 5</td>
... <td class="txt_r">21,850</td>
... <td class="txt_r">39</td>
... </tr>
... </table> """, "lxml")
>>> this_td = html.find("th", class_="fuku")
>>> td_list = this_td.parent.find_all("td")
>>> td_list
[<td>2<br/>5<br/>6</td>, <td class="txt_r">170<br/>1,340<br/>310</td>, <td class="txt_r">2<br/>12<br/>6</td>]

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

テーブルの1行ずつのデータ取りたいってことですかね?
find_all(“tr”)してforとかで回せば取れそうですが試してみたでしょうか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • ただいまの回答率 90.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Python 3.x

    7369questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。