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

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

ただいまの
回答率

88.33%

BeautifulSoup4のfind_allでタグの中の文章が取得できない

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 11K+

hhhhhhhhh

score 13

前提・実現したいこと

<strong style="color:#C84B00;font-size: 16px;">犬</strong>
<strong style="color:#C84B00;font-size: 16px;">猫</strong>
上記で言う「犬」「猫」のような
複数の要素を持つタグに含まれている、内容だけを取得したいです。※idやclassがありません。
(本来はこちらのソースを取得しています)

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

複数の該当する内容を取得したいので.find_all()を利用しています。
詳細は該当のソースコードに記載しています。

"ResultSet object has no attribute '%s'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?" % key
AttributeError: ResultSet object has no attribute 'text'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?
Exited with status 1 after 0.26 seconds

該当のソースコード

import urllib.request
from bs4 import BeautifulSoup
html = urllib.request.urlopen("http://yume-uranai.jp/keyword.php?keyword=%8C%A2&q=1")
soup = BeautifulSoup(html, "html.parser")
title = soup.find_all("strong",style="color:#C84B00;font-size: 16px;")
print(title.text)

調べたこと

この質問では、.stringの位置が違うんじゃないか?と言う回答が寄せられていました。
.stringは、.textと違い、1つの要素の時に使うものだと認識しております。
こちらを読みましたが、まだよく理解していません。とりあえず、.textが大味な意味で使える物と言う認識もしています。
質問を参考に.textの位置を変えて見ました。

title = soup.find_all("strong",style="color:#C84B00;font-size: 16px;".text)
print(title)


もしくはこちらも

title = soup.find_all("strong",style="color:#C84B00;font-size: 16px;").text
print(title)


どちらとも最初と同じエラーメッセージが出ます。

しかし、print(title)を使わずに、このようにforで1つずつ取り出すと正しく中身だけを抜くことができました。

for i in title:
    print(i.text)

以下の参考にした記事全て、このようなfor文での書き方はしていません。
https://qiita.com/itkr/items/513318a9b5b92bd56185
https://qiita.com/connectcrew-ishii/items/6ad316ea854326c536a6
http://python.zombie-hunting-club.com/entry/2017/11/08/192731

僕の調べ方が悪いのか、また分からなさすぎて理解が足りていないだけなのか、恐らくその両方だと思いますが
forを使わずに、find_allで文章だけ取得することは不可能なのでしょうか?
僕はこの結果を配列に格納したいのですが、せっかくfind_allで取得した、タグも含まれている配列をfor文で出力し
また別の配列に入れなければなりません。
最初から、find_allで中身だけ取り出せれば良い物だと思うのですが、全くやり方がわかりません。

右も左も分からないレベルに初心者なので、エンジニアの方が想定している考え方が全くできていないと思いますが、ご回答していただければ幸いです。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

find_allは複数の要素を返すので、forループを使うしかありません。
.stringでも.textでも関係ありません。
提示URLhttps://qiita.com/connectcrew-ishii/items/6ad316ea854326c536a6でも、(selectで要素を取得していますが)実際のtextを取得するさいはforループを利用しています。

forを使わずに、find_allで文章だけ取得することは不可能なのでしょうか?
僕はこの結果を配列に格納したいのですが、せっかくfind_allで取得した、タグも含まれている配列をfor文で出力し
また別の配列に入れなければなりません。
最初から、find_allで中身だけ取り出せれば良い物だと思うのですが、全くやり方がわかりません。

以下でよいのではないでしょうか?

# 略
ret = []
for t in title:
    ret.append(t.text)
#ret = [t.text for t in title] # これでもよい

print(ret) # ['犬', '子犬', ~]

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/12/24 17:25

    ご回答ありがとうございます。
    タグから取得する際に正規表現よりユニークなタグを指定しており、内包表記の実用性が高いため、こちらをベストアンサーにさせていただきました。tiitoiさんもご回答ありがうございました。正規表現についてももっと勉強してみたいと思います。

    以下のコメントは回答義務はありません。
    初学者なのでよく詰まり自力で解決できず、諦めることの多い僕の疑問です。お時間のある際、気が向いた時などにお答え頂ければすごく嬉しいです。(書いて頂かなくても構いません。)

    今回の質問は大方自分の中で解決した後に疑問点を質問していたので、コードの完成自体はなんとかなったのですが
    本当に何が何だか分からない場合はみなさんどうしていますか?
    今回bs4として質問致しましたが、本来私はseleniumで情報を取得して来ようと思っていました。
    しかし、要素の取得がうまくいかずbs4にソース丸投げで対応するという結果になりました。(恐らくこの対応は今後seleniumの操作で泣きを見そうです)
    また、その逃げた先のbs4でもこの通り、qiitaの記事を読んでも理解できず...と言う結果でした。

    僕は大抵、質問する以前に「どこが分からないのかすら分からない」と言う状態になっています。
    恐らくそう言う時は人に現在知っていることや詰まっている状態をそのまま見せて相談すると思うのですが、孤独にコーディングしている為、そう言う友達がいません...
    検索も未知には対応していないので、検索をしても知っていることしか分かりませんでした。
    テラテイルは「15分調べても分からないことは、質問しよう!」とのことですが、恐らくその状態の質問内容は稚拙すぎて苦情が出ます。それが怖くて今まで質問できませんでした。
    大方経験者からは、調べれば分かるだろ!と思う内容について、僕も質問しているのではないかと思っています。

    なるべく自力で解決するために、みなさんがどの様にして未知の問題について対応しているのかご教授いただければ幸いです。
    基本的なpythonの扱いはできているかな?と思っているので、主にライブラリやフレームワークなどの勉強方法について教えていただければ幸いです。

    キャンセル

  • 2018/12/24 20:17

    「どこが分からないのかすら分からない」状態では質問はしないほうがよいと考えています。
    以下、私が実践してきた方法です。
    まず、そのような状態の場合、もっと簡単な問題から取り組むようにしてきました。
    また、いきなりやりたいことをコーディングしようとするのではなく、入門書や公式のマニュアル、チュートリアルを**分かるまで繰り返し繰り返し繰り返し…**やってきました。
    簡単な問題から、徐々にやりたいことへ近づいていく感じです。

    なお、質問者様の疑問、質問は私も含め多くの初心者が通ってきた道なので、新たに別途質問を立てると
    多くの人から有益なアドバイスなり類似の過去質問を紹介してもらえる可能性があります。

    キャンセル

+1

find_all(), find() に text 引数を指定することで、指定した値を持つ要素を検索できます。
この指定には正規表現が利用できるので、次のようにしてみてはどうでしょうか。

import re
import urllib.request
from bs4 import BeautifulSoup

url = 'http://yume-uranai.jp/keyword.php?keyword=%8C%A2&q=1'
html = urllib.request.urlopen(url)
soup = BeautifulSoup(html, 'html.parser')

# 要素名が strong で値に犬または猫を含む要素を抽出
elems = soup.find_all('strong', text=re.compile('(犬|猫)'))

# 結果
for elem in elems:
    print(elem.string)
犬
子犬
犬に噛まれる
犬を飼う
犬と散歩する
大型犬
犬に吠えられる
犬と遊ぶ
犬を躾ける
愛犬

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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