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

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

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

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

Q&A

解決済

2回答

520閲覧

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

threeeverytwo

総合スコア49

Python 3.x

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

0グッド

0クリップ

投稿2018/02/25 18:35

編集2018/02/27 15:29

前提・実現したいこと

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

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

HTML

1<li class="text-en text-c"> 2A 3<a href="/word/en/change/#ej-14756"> 4<span class="a_line"> 5<span class="a_moji" title="changeの意味">change</span> 6</span> 7</a> 8<a href="/word/en/of/#ej-58587"> 9<span class="a_line"> 10<span class="a_moji" title="ofの意味"> 11of 12</span> 13</span> 14</a> 15<a href="/word/en/air/#ej-1635"> 16<span class="a_line"> 17<span class="a_moji" title="airの意味"> 18air 19</span> 20</span> 21</a> 22<a href="/word/en/always/#ej-2421"> 23<span class="a_line"> 24<span class="a_moji" title="alwaysの意味"> 25always 26</span> 27</span> 28</a> 29<i><i>profit</i>s</i> 30<a href="/word/en/in/#ej-43166"> 31<span class="a_line"> 32<span class="a_moji" title="inの意味"> 33in 34</span> 35</span> 36</a> 37<a href="/word/en/your/#ej-96280"> 38<span class="a_line"> 39<span class="a_moji" title="yourの意味"> 40your 41</span> 42</span> 43</a> 44<a href="/word/en/case/#ej-13775"> 45<span class="a_line"> 46<span class="a_moji" title="caseの意味"> 47case 48</span> 49</span> 50</a> 51. 52</li> 53 54

該当のソースコード

python

1from bs4 import BeautifulSoup 2 3contentsList = 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'>

試したこと

python

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

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

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

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

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

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

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

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

guest

回答2

0

ベストアンサー

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

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


2018/02/28追記

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

Python

1# -*- coding: utf8 -*- 2from bs4 import BeautifulSoup, NavigableString 3 4 5def get_content(): 6 body = """ 7 <li class="text-en text-c"> 8 A 9 <a href="/word/en/change/#ej-14756"> 10 <span class="a_line"> 11 <span class="a_moji" title="changeの意味">change</span> 12 </span> 13 </a> 14 <a href="/word/en/of/#ej-58587"> 15 <span class="a_line"> 16 <span class="a_moji" title="ofの意味"> 17 of 18 </span> 19 </span> 20 </a> 21 <a href="/word/en/air/#ej-1635"> 22 <span class="a_line"> 23 <span class="a_moji" title="airの意味"> 24 air 25 </span> 26 </span> 27 </a> 28 <a href="/word/en/always/#ej-2421"> 29 <span class="a_line"> 30 <span class="a_moji" title="alwaysの意味"> 31 always 32 </span> 33 </span> 34 </a> 35 <i><i>profit</i>s</i> 36 <a href="/word/en/in/#ej-43166"> 37 <span class="a_line"> 38 <span class="a_moji" title="inの意味"> 39 in 40 </span> 41 </span> 42 </a> 43 <a href="/word/en/your/#ej-96280"> 44 <span class="a_line"> 45 <span class="a_moji" title="yourの意味"> 46 your 47 </span> 48 </span> 49 </a> 50 <a href="/word/en/case/#ej-13775"> 51 <span class="a_line"> 52 <span class="a_moji" title="caseの意味"> 53 case 54 </span> 55 </span> 56 </a> 57 . 58 </li> 59 60 """ 61 return BeautifulSoup(body, "html.parser") 62 63 64def main() -> None: 65 soup = get_content() 66 contentsList = soup.find("li", class_="text-en text-c").contents 67 for _, data in enumerate(contentsList): 68 if len(data) == 0: 69 continue 70 if isinstance(data, NavigableString): 71 continue 72 print("#" * 40) 73 print(data.text.strip()) 74 75 76if __name__ == '__main__': 77 main() 78

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

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

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

Python

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

投稿2018/02/27 14:26

編集2018/02/27 16:14
umyu

総合スコア5846

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

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

threeeverytwo

2018/02/27 14:32

下記のようなエラーが返ってきます。 AttributeError: 'str' object has no attribute 'text'
umyu

2018/02/27 14:40

>AttributeError: 'str' object has no attribute 'text' 推測だと文字列の長さが0の文字列に対しても処理を行っているように見受けられますが、 お手数ですが、質問文に変数soupに代入しているHTMLを追加してくださいな。
threeeverytwo

2018/02/27 14:47

勉強不足で申し訳ないのですが、変数soupに代入しているHTMLは、 soup.find("li", class_ = "text-en text-c") の値で合っていますか?
umyu

2018/02/27 14:50 編集

soup.findを行っている前の行で変数 soupに値を代入していませんか?
threeeverytwo

2018/02/27 15:01

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

2018/02/27 16:03

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

2018/02/27 16:49

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

0

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

python

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

投稿2018/02/25 23:14

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問