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

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

新規登録して質問してみよう
ただいま回答率
85.50%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Beautiful Soup

Beautiful Soupは、Pythonのライブラリの一つ。スクレイピングに特化しています。HTMLデータの構文の解析を行うために、HTMLタグ/CSSのセレクタで抽出する部分を指定することが可能です。

Python 3.x

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

Q&A

解決済

2回答

2593閲覧

【Python】このスクレイピングコードは何がいけないのでしょうか

RinKawakami

総合スコア20

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Beautiful Soup

Beautiful Soupは、Pythonのライブラリの一つ。スクレイピングに特化しています。HTMLデータの構文の解析を行うために、HTMLタグ/CSSのセレクタで抽出する部分を指定することが可能です。

Python 3.x

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

1グッド

1クリップ

投稿2019/01/21 08:48

前提・実現したいこと

教本をみながらスクレイピング練習中なのですが、
自分のコードでは動きません。

「どこが間違っているか」はわかるのですが、
「なぜ間違っているのか」教えていただきたいです。

課題内容

練習用サイトアクセスし、
以下の<div>に含まれる、<a>タグで囲われた文字列を抽出して出力する

<div class="list-group"> <a href="#" class="list-group-item" data-slimstat="5">トップページ</a><br> <a href="/company" class="list-group-item" data-slimstat="5">会社案内</a><br> <a href="/company/greeting" class="list-group-item" data-slimstat="5">代表挨拶</a><br> <a href="/services/advisory_engineer" class="list-group-item" data-slimstat="5">顧問エンジニアによるITコンサルティング</a><br> <a href="/services/handy" class="list-group-item" data-slimstat="5">展示会の注文管理サービス Handy</a><br> <a href="/services/mod99" class="list-group-item" data-slimstat="5">業務システム自動生成フレームワーク MOD99</a><br> <a href="/category/advisory_engineer_column" class="list-group-item" data-slimstat="5">IT活用虎の巻</a><br> <a href="/dokushu-python-support" class="list-group-item" data-slimstat="5">独習Python入門サポートページ</a><br> <a href="/contact" class="list-group-item" data-slimstat="5">お問い合わせ</a> </div>

提示された手順

①divタグを抽出する
②divタグに囲われている、全てのaタグを配列で抽出する
③②で取得した配列を繰り返し処理で出力

###教本での解法

Python

1import urllib.request 2from bs4 import BeautifulSoup 3 4req = urllib.request.urlopen("https://quality-start.in/company/") 5soup = BeautifulSoup(req, "html.parser") 6side_menu = soup.find("div", class_="list-group") 7 8for a_tags in side_menu.find_all("a"): 9 print(a_tags.string)

自分が書いたコード

Python

1import urllib.request 2from bs4 import BeautifulSoup 3 4req = urllib.request.urlopen("https://quality-start.in/company/") 5soup = BeautifulSoup(req, "html.parser") 6side_menu = soup.find("div", class_="list-group") 7 8items = side_menu.find_all("a").string 9 10for i in items: 11 print(i)

聞きたいこと

自分のコードでは、aタグをitemsという配列に一旦格納してから、for文で出力している(つもり)で、
教本は、配列に名前をつけず、直接for文に突っ込んで出力している、といったところでしょうか。

自分のコードではこのようなエラーが出てしまい、実行されません。

Traceback (most recent call last): File "do_scraping.py", line 8, in <module> items = side_menu.find_all("a").string File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/bs4/element.py", line 1620, in __getattr__ "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 'string'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?

①なぜこのようなことが起こるのでしょうか
②もし、自分のコードのように、aタグの中身を配列として変数に代入する場合、どのように書かなければいけなかったのでしょうか

教えていただけると嬉しいです。
よろしくお願いします。

oasis701👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

①なぜこのようなことが起こるのでしょうか

AttributeError: ResultSet object has no attribute 'string'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?

日本語に訳すと

Attribute エラー: ResultSet オブジェクトは 'string' という attribute を持っていません。タグのリストをタグと勘違いして使っていませんか?find() を呼ぶべきところで find_all() を呼んでいませんか?

find_all() の返り値は bs4.element.ResultSet オブジェクトです。
このオブジェクトは bs4.element.Tag オブジェクトのリストと考えてよいです。
.string というタグのテキストを取得する attribute は bs4.element.ResultSet ではなく、bs4.element.Tag の持つ属性なので、

side_menu.find_all("a").string とすると bs4.element.ResultSet は string という attribute は持っていないとエラーになります。

②もし、自分のコードのように、aタグの中身を配列として変数に代入する場合、どのように書かなければいけなかったのでしょうか

テキストのリストとして得たいのであれば、各 a タグの string 属性を要素にして、リストを作成すればよいです。

python

1import urllib.request 2from bs4 import BeautifulSoup 3 4req = urllib.request.urlopen("https://quality-start.in/company/") 5soup = BeautifulSoup(req, "html.parser") 6 7side_menu = soup.find("div", class_="list-group") 8 9div_texts = [a.string for a in side_menu.find_all("a")] 10print(div_texts)
['トップページ', '会社案内', '代表挨拶', '顧問エンジニアによるITコンサルティング', '展示会の注文管理サービス Handy', '業務システム自動生成フレームワーク MOD99', 'IT活用虎の巻', '独習Python入門サポートページ', 'お問い合わせ']

投稿2019/01/21 08:57

編集2019/01/21 09:05
tiitoi

総合スコア21954

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

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

RinKawakami

2019/01/21 09:26

素早く詳しい回答ありがとうございます。 説明で記載していただいたコードで言いますと、 「side_menu」=配列(値の集合体)であり、bs4.element.ResultSetのオブジェクト for a in side_menu.find_all("a") における「a」=個々の値であり、bs4.element.Tagのオブジェクト そのため、side_menuそのものに「.string」は使用できないが、 繰り返しで抽出した各要素aには「.string」を使用できる・・・ という認識で合っていますか? 専門用語や概念がまだ身についていない自分用に、もう少し平たくいうと find_all()で抽出した値は、配列なので、それごと「.string」を用いることはできないけれど 一つ一つを取り出してきてあげれば、「.string」を使っても良い ・・・と言っても間違いではないでしょうか?
tiitoi

2019/01/21 09:33 編集

コメントの認識であっています bs4.element.ResultSet は [bs4.element.Tag, bs4.element.Tag, ...] という配列だと思えばよいです。 find_all('a') なので、a タグの一覧を取得するという意味なので、返り値は配列になります。
hit701

2019/01/21 14:31

同じく、スクライビングの勉強をしている者です。 tiitoiさんが求めているコードを回答欄に記載してみましたので、よろしくお願いします。
tiitoi

2019/01/21 14:51

hit701 さん、コメントありがとうございます。 回答いただいた内容で .string の使い方はあっています。 今回は print() 文で出力するのではなく、「複数ある a 要素の値を配列として得たい」という質問内容でしたので、 div_texts = [a.string for a in side_menu.find_all("a")] と回答欄のコードには記載しました。
guest

0

同じくスクライビングの勉強している者ですが、RinKawakamiさんの最終的なコードは、下記でよろしいでしょうか?

python

1import urllib.request 2from bs4 import BeautifulSoup 3 4req = urllib.request.urlopen("https://quality-start.in/company/") 5soup = BeautifulSoup(req, "html.parser") 6side_menu = soup.find("div", class_="list-group") 7 8items = side_menu.find_all("a") ←stringを外しました。 9 10for i in items: 11 print(i.string)

これで教本と同じ結果がでました。
少し分かって来ました。
質問して下さってありがとうございます。

投稿2019/01/21 14:29

編集2019/01/22 12:24
hit701

総合スコア148

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問