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

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

ただいまの
回答率

89.55%

beautifulsoup4 を使って、入れ子になっているタグ内の要素を取り出したいが、行き詰っている。

解決済

回答 2

投稿 編集

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

Kaiji.Anabuki

score 35

 前提・実現したいこと

contentsList の <i><i>profit</i>s</i> の profits のみを取り出したい。

変数soupに代入されているHTML

<li class="text-en text-c">
A 
<a href="/word/en/change/#ej-14756">
<span class="a_line">
<span class="a_moji" title="changeの意味">change</span>
</span>
</a> 
<a href="/word/en/of/#ej-58587">
<span class="a_line">
<span class="a_moji" title="ofの意味">
of
</span>
</span>
</a> 
<a href="/word/en/air/#ej-1635">
<span class="a_line">
<span class="a_moji" title="airの意味">
air
</span>
</span>
</a> 
<a href="/word/en/always/#ej-2421">
<span class="a_line">
<span class="a_moji" title="alwaysの意味">
always
</span>
</span>
</a> 
<i><i>profit</i>s</i> 
<a href="/word/en/in/#ej-43166">
<span class="a_line">
<span class="a_moji" title="inの意味">
in
</span>
</span>
</a> 
<a href="/word/en/your/#ej-96280">
<span class="a_line">
<span class="a_moji" title="yourの意味">
your
</span>
</span>
</a> 
<a href="/word/en/case/#ej-13775">
<span class="a_line">
<span class="a_moji" title="caseの意味">
case
</span>
</span>
</a>
.
</li>

 該当のソースコード

from bs4 import BeautifulSoup

contentsList = soup.find("li", class_ = "text-en text-c").contents

上記の contentsList を出力すると

['A ', 
<a href="/word/en/change/#ej-14756"><span class="a_line"><span class="a_moji" title="changeの意味">change</span></span></a>,
' ',
<a href="/word/en/of/#ej-58587"><span class="a_line"><span class="a_moji" title="ofの意味">of</span></span></a>,
' ',
<a href="/word/en/air/#ej-1635"><span class="a_line"><span class="a_moji" title="airの意味">air</span></span></a>,
' ',
<a href="/word/en/always/#ej-2421"><span class="a_line"><span class="a_moji" title="alwaysの意味">always</span></span></a>,
' ',
<i><i>profit</i>s</i>,
' ',
<a href="/word/en/in/#ej-43166"><span class="a_line"><span class="a_moji" title="inの意味">in</span></span></a>,
' ',
<a href="/word/en/your/#ej-96280"><span class="a_line"><span class="a_moji" title="your の意味">your</span></span></a>,
' ',
<a href="/word/en/case/#ej-13775"><span class="a_line"><span class="a_moji" title="caseの意味">case</span></span></a>,
'.']

contentsList の 中身の型を調べると

contentsList[0] : A
type : <class 'bs4.element.NavigableString'>

contentsList[1] : <a href="/word/en/change/#ej-14756"><span class="a_line"><span class="a_moji" title="changeの意味">change</span></span></a>
type : <class 'bs4.element.Tag'>

contentsList[2] :
type : <class 'bs4.element.NavigableString'>

contentsList[3] : <a href="/word/en/of/#ej-58587"><span class="a_line"><span class="a_moji" title="ofの意味">of</span></span></a>
type : <class 'bs4.element.Tag'>

contentsList[4] :
type : <class 'bs4.element.NavigableString'>

contentsList[5] : <a href="/word/en/air/#ej-1635"><span class="a_line"><span class="a_moji" title="airの意味">air</span></span></a>
type : <class 'bs4.element.Tag'>

contentsList[6] :
type : <class 'bs4.element.NavigableString'>

contentsList[7] : <a href="/word/en/always/#ej-2421"><span class="a_line"><span class="a_moji" title="alwaysの意味">always</span></span></a>
type : <class 'bs4.element.Tag'>

contentsList[8] :
type : <class 'bs4.element.NavigableString'>

contentsList[9] : <i><i>profit</i>s</i>
type : <class 'bs4.element.Tag'>

contentsList[10] :
type : <class 'bs4.element.NavigableString'>

contentsList[11] : <a href="/word/en/in/#ej-43166"><span class="a_line"><span class="a_moji" title="inの意味">in</span></span></a>
type : <class 'bs4.element.Tag'>

contentsList[12] :
type : <class 'bs4.element.NavigableString'>

contentsList[13] : <a href="/word/en/your/#ej-96280"><span class="a_line"><span class="a_moji" title="yourの意味">your</span></span></a>
type : <class 'bs4.element.Tag'>

contentsList[14] :
type : <class 'bs4.element.NavigableString'>

contentsList[15] : <a href="/word/en/case/#ej-13775"><span class="a_line"><span class="a_moji" title="caseの意味">case</span></span></a>
type : <class 'bs4.element.Tag'>

contentsList[16] : .
type : <class 'bs4.element.NavigableString'>

 試したこと

for index in range(len(contentsList)):
    print(contentsList[index].string)


上記のコードで取得しようとしたが、contentsList[9]のみタグ内にタグがあり、文字列を抜き出せない。

出力結果としては、contentsList[9]は、"None" が 返却される。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

0

スクレイピングの時、入れ子の要素をうまく取得する方法

contentsList[index].text で取得できませんか?


2018/02/28追記

以下のソースコードでどうでしょうか?

# -*- coding: utf8 -*-
from bs4 import BeautifulSoup, NavigableString


def get_content():
    body = """
    <li class="text-en text-c">
    A 
    <a href="/word/en/change/#ej-14756">
    <span class="a_line">
    <span class="a_moji" title="changeの意味">change</span>
    </span>
    </a> 
    <a href="/word/en/of/#ej-58587">
    <span class="a_line">
    <span class="a_moji" title="ofの意味">
    of
    </span>
    </span>
    </a> 
    <a href="/word/en/air/#ej-1635">
    <span class="a_line">
    <span class="a_moji" title="airの意味">
    air
    </span>
    </span>
    </a> 
    <a href="/word/en/always/#ej-2421">
    <span class="a_line">
    <span class="a_moji" title="alwaysの意味">
    always
    </span>
    </span>
    </a> 
    <i><i>profit</i>s</i> 
    <a href="/word/en/in/#ej-43166">
    <span class="a_line">
    <span class="a_moji" title="inの意味">
    in
    </span>
    </span>
    </a> 
    <a href="/word/en/your/#ej-96280">
    <span class="a_line">
    <span class="a_moji" title="yourの意味">
    your
    </span>
    </span>
    </a> 
    <a href="/word/en/case/#ej-13775">
    <span class="a_line">
    <span class="a_moji" title="caseの意味">
    case
    </span>
    </span>
    </a>
    .
    </li>

    """
    return BeautifulSoup(body, "html.parser")


def main() -> None:
    soup = get_content()
    contentsList = soup.find("li", class_="text-en text-c").contents
    for _, data in enumerate(contentsList):
        if len(data) == 0:
            continue
        if isinstance(data, NavigableString):
            continue
        print("#" * 40)
        print(data.text.strip())


if __name__ == '__main__':
    main()

■参考情報
Beautiful Soup 4.2.0 Doc. 日本語訳
str.strip

別回答も置いておきます。
前提条件として liの子要素にi要素が必ず1個だけ存在する。

というのを仮定できるならば以下のコードでも取得できます。

    tag = soup.find("li", class_="text-en text-c")
    print(tag.i.text.strip())

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/02/28 00:01

    soupに代入しているHTMLを記載いたしました。

    キャンセル

  • 2018/02/28 01:03

    質問文に追加ありがとうございます。

    キャンセル

  • 2018/02/28 01:49

    大変助かりました。ありがとうございました。

    キャンセル

0

正規表現を使えば出来るみたいです。

import re
text ='<a href="/word/en/change/#ej-14756"><span class="a_line"><span class="a_moji" title="changeの意味">change</span></span></a>'
text = re.sub('<[^>]*>', '', text)
print(text)
# change

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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