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

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

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

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

Python 3.x

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

Q&A

解決済

1回答

6878閲覧

Beautiful Soup4で返ってくるオブジェクトのTypeによって条件分岐したい!

hacosato

総合スコア48

スクレイピング

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

Python 3.x

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

0グッド

0クリップ

投稿2017/03/25 14:06

編集2017/03/25 14:08

Beautiful Soup4の質問ってよりかはPythonの質問なのかな…。

こんにちは。
Beautiful Soupでスクレイピングをしています。
返ってくるオブジェクトのTypeによって処理を変えたいですが、やり方がわかりません…。

あるHTMLにたいして、spanをすべて調べようとしました。

from bs4 import BeautifulSoup as soup html = '0<span class="a">1<span class="b"><span class="c">2</span></span></span>' doc = soup(html, "lxml") for item in doc.find_all("span"): print(type(item.contents[0]))

↑これを実行すると、

<class 'bs4.element.NavigableString'> <class 'bs4.element.Tag'> <class 'bs4.element.NavigableString'>

↑こういうのが返ってきました。

NavigableStringかTagかによって処理を変えたいです。

from bs4 import BeautifulSoup as soup html = '0<span class="a">1<span class="b"><span class="c">2</span></span></span>' doc = soup(html, "lxml") for item in doc.find_all("span"): if type(item.contents[0]) == 'bs4.element.NavigableString': print("NavigableStringです") elif type(item.contents[0]) == 'bs4.element.Tag': print("Tagです") else: print("どちらでもないです")

↑これを実行して、

NavigableStringです Tagです NavigableStringです

↑こういう結果がほしいです。

実際には

どちらでもないです どちらでもないです どちらでもないです

↑こうなってしまいます。こまってしまいました…。

わたしの力ではどうしようもないWebページをスクレイピングしているので、Typeで見分ける以外の方法は使えそうにありません。

お力添えいただけるとうれしいです!

###補足情報(言語/FW/ツール等のバージョンなど)
Python 3.5
Beautiful Soup 4.4.1

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

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

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

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

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

guest

回答1

0

ベストアンサー

type が返すのは「文字列」ではありません。引数として渡したオブジェクトの型となる「クラス」を返します。なので下記のようにすれば良いです。

python

1from bs4 import BeautifulSoup as soup 2from bs4.element import NavigableString, Tag 3 4html = '0<span class="a">1<span class="b"><span class="c">2</span></span></span>' 5doc = soup(html, "lxml") 6for item in doc.find_all("span"): 7 if type(item.contents[0]) is NavigableString: 8 print("NavigableStringです") 9 elif type(item.contents[0]) is Tag: 10 print("Tagです") 11 else: 12 print("どちらでもないです")

追記(2017/03/27)  

terapon さんからコメントでもらった内容も追記しておきます。 例えば、NavigableString の子クラスには element.Comment などが存在します。そういう親子関係にあるものも一緒にチェックしたいといった場合には、 isinstance を使う方がよりスマートにチェックできます。

python

1# -*- coding: utf-8 -*- 2 3from bs4 import BeautifulSoup as soup 4from bs4.element import NavigableString, Tag 5 6# コメント(<!-- comment -->) が追加されている 7html = '<span><!-- comment --><span class="a">1<span class="b"><span class="c">2</span></span></span></span>' 8doc = soup(html, "lxml") 9for item in doc.find_all("span"): 10 # element.Comment は NavigableString の子クラスなので、ここで一緒にチェックされる 11 # NavigableString の子クラス(孫クラス) は Comment以外にもいっぱいあるので、それらを全てここでチェックできる。 12 if isinstance(item.contents[0], NavigableString): 13 print("NavigableString(又はComment)です") 14 elif isinstance(item.contents[0], Tag): 15 print("Tagです") 16 else: 17 print("どちらでもないです")

参考

投稿2017/03/25 18:29

編集2017/03/26 03:05
tell_k

総合スコア2120

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

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

terapyon

2017/03/26 01:49

type関数を使う方法も可能ですが、 isinstance関数を使ったほうが継承元も含めた評価になるので良いと思います。 type(item.contents[0]) is NavigableString ↓ isinstance(item.contents[0]), NavigableString)
hacosato

2017/03/26 02:40

tell_kさん回答ありがとうございます。うごきました! 文字列じゃないよな…とは思っていたものの、やり方がわかりませんでした。 この質問をする前に「is」を使ったものも試してみていたんですが、そのときには以下のようにしていたため、動きませんでした。 ``` if type(item.contents[0]) is bs4.element.NavigableString: ``` 「.」でsplitして最後の項目を当てはめれば動くんだと思うんですが、 この「.」はなんですか? スーパークラスかな…? 質問重ねてしまいすみません…。
hacosato

2017/03/26 02:46

terapyonさんコメントありがとうございます。 isinstance関数のほうがいいみたいなことは、ネットで調べてなんとなくわかりました。 strとかintとかみたいに簡単な場合はいいんですが、 今回のようにちょっと変わったクラスでやりたいとして、 まずはどんなクラスか調査したいときにはどうしたらいいのでしょうか? ``` print(type(item.contents[0])) ``` そのときにはtype関数でいいですか? isinstance関数をオープンクエスチョンみたいに使う方法があれば知りたいです!
tell_k

2017/03/26 15:15 編集

> if type(item.contents[0]) is bs4.element.NavigableString: このやり方は間違っていません。私の最初の解答と同じやり方です。多分その時の見間違いか、他にエラーになる要因があったのかもしれません。 > この「.」はなんですか? パッケージ/モジュールの区切りの文字が「.」です チュートリアルのモジュールの章を読んでみてください。 http://docs.python.jp/3/tutorial/modules.html > まずはどんなクラスか調査したいときにはどうしたらいいのでしょうか? ソースは公開されているので、私はそこから調べました。IDEや補完ツールを使うと簡単に調べられるかもしれません。 https://pypi.python.org/pypi/beautifulsoup4
hacosato

2017/03/26 04:08

> if type(item.contents[0]) is bs4.element.NavigableString: これを実行すると、 > NameError: name 'bs4' is not defined と表示されます…。importがよくないのでしょうか? その他の部分はわかってきました。ありがとうございました!
tell_k

2017/03/26 15:15 編集

> と表示されます…。importがよくないのでしょうか? importが良くないですね。ファイルの先頭行に「import bs4」と一行付け加えてみてください。多分それでそのエラーはでなくなるはずです。
hacosato

2017/03/29 15:35

返信が遅くなってしまってすみません…。 import bs4を追記したら動くようになりました。ありがとうございます。 手元にPythonの入門書を持っていて、前半はひととおり読んでいるはずなのですが、なかなか肌にあわない本を選んでしまったのかimportのあたりがいつまで経ってもぴんときません…。勉強しよう!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問