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

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

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

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

Beautiful Soup

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

関数を()なしで実行できている意味がわからない(Udemy講座)

KimuraSouki
KimuraSouki

総合スコア1

スクレイピング

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

Beautiful Soup

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

4回答

0グッド

1クリップ

531閲覧

投稿2022/10/12 07:46

編集2022/10/12 07:48

発生している問題

pythonのBeautifulSoup講座をUdemyで学んでおります。定義した関数を()をつけずに実行していて成立している意味がわからないので教えていただきたいです。

該当のソースコード

python

1html =''' 2 3<html> 4 <head> 5 <title>清水義孝の著書</title> 6 </head> 7 <body> 8 <p class="title"> 9 <b>清水義孝の最新の著書には、次の本があります。</b> 10 </p> 11 <p class="recent books"> 12 <a class="book" href="https://www.amazon.co.jp/dp/B07TN4D3HG" id="link1"> 13 Python3によるビジネスに役立つデータ分析入門 14 </a> 15 <a class="book" href="http://www.amazon.co.jp/dp/B07SRLRS4M" id="link2"> 16 よくわかるPython3入門2.NumPy・Matplotlib編 17 </a> 18 <a class="book" href="http://www.amazon.co.jp/dp/B07T9SZ96B" id="link3"> 19 よくわかるPython3入門4.Pandasでデータ分析編 20 </a> 21 </p> 22 <p class="end"> 23 <b>そして、これらの本は好評発売中です。</b> 24 </p> 25 </body> 26</html> 27''' 28 29soup = BeautifulSoup(html,'html.parser') 30 31#class属性があって、id属性がないタグの要素を取得 32def has_class_but_no_id(tag): 33 return tag.has_attr('class') and not tag.has_attr('id') 34 35soup.find_all(has_class_but_no_id)

補足情報(FW/ツールのバージョンなど)

python 3.9.13
beautifulsoup4 4.11.1

該当箇所はソースコード一番下の

def has_class_but_no_id(tag): return tag.has_attr('class') and not tag.has_attr('id') soup.find_all(has_class_but_no_id)

という箇所です。
「class属性があって、id属性がないタグの要素を取得する」というコードです。
has_class_but_no_idに(tag)がついていないのに正しく処理される意味がわかりません。
関数は「関数()」と記述して実行するものではないのでしょうか。
また、tagがないにもかかわらずsoupの中身を使えているのはどういった仕組みだからでしょうか。

以下のような質問にはグッドを送りましょう

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

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

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

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

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

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

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

適切な質問に修正を依頼しましょう。

回答4

1

以下のプログラムを実行すると Hello, world! がprintされる仕組みは理解できますか?

python

1def has_class_but_not_id(tag): 2 print(tag) 3 4def find_all(callback): 5 callback("Hello, world!") 6 7find_all(has_class_but_not_id)

投稿2022/10/12 08:58

shiracamus

総合スコア5394

quickquip👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

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

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

このような回答には修正を依頼しましょう。

1

ベストアンサー

find_all()にはCallableを渡すことができます.

Beautiful Soup Documentation - A Function

tagがないにもかかわらずsoupの中身を使えているのはどういった仕組みだからでしょうか

このCallablehas_class_but_no_idに,find_all()の内部でtagを渡して,has_class_but_no_id(tag)と書いたことになるようなコードを実装しています.

find_all()の実態は,SoupStrainerによる変換が行われ,SoupStrainer()._normalize_search_value()による検索手順の正規化が行われていることが知られています.find_all()の第一引数にCallableとして渡したnameは,SoupStrainer()._normalize_search_value()callable(value)というチェックを受けSoupStrainerの中にSoupStrainer().nameで残ります.その後,find_all()の中でstrainer.search(i)で渡されたtagであるiを使って,SoupStrainer().search_tag()にてCallableであるself.nameself._match(markup, self.name)に渡して関数として利用していることがわかります.ユーザ観点ではhas_class_but_no_id(tag)が実行されますが,内部的にはmatch_against(markup)と書かれて関数が呼び出されています.

PythonでCallableを渡すことは多々あるので使っていると違和感もなくなるでしょう.

Python

1def f1(x, y): 2 return x + y 3 4def f2(x, y): 5 return x * y 6 7def result(func, x, y): 8 return func(x, y) 9 10print(result(f1, 2, 3)) # 5 11print(result(f2, 2, 3)) # 6

組み込み関数map()の第一引数はCallable,第二引数はIterableであることもよく使われます.

Python

1def f1(x): 2 return x[0] + x[1] 3 4def f2(x): 5 return x[0] * x[1] 6 7a = [[1, 2], [3, 4], [5, 6]] 8print(a) 9print(list(map(f1, a))) # [3, 7, 11] 10print(list(map(f2, a))) # [2, 12, 30] 11print(list(map(lambda x: x[0] ** x[1], a))) # [1, 81, 15625]

投稿2022/10/12 08:11

編集2022/10/12 12:27
PondVillege

総合スコア1050

ockeghem👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

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

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

このような回答には修正を依頼しましょう。

回答へのコメント

KimuraSouki

2022/10/24 23:03

ありがとうございます。 初心者の自分にとって難しい解答ではありましたが、わかりやすい具体例と合わせて説明していただき、直感的にfind_all()にそういった機能があるのだということがわかりました。

0

関数名に括弧を付けずに、変数に代入したり、別の関数の引数に渡したりするのは、ごく普通です。
代入や引数で渡す時点で呼び出されるのじゃなくて、後に括弧を付けた時点で関数が呼び出されます。

Python

1def foo(): 2 print("called") 3 4print("ここでは呼ばれない") 5a = foo 6 7print("ここで呼ばれる") 8a()

投稿2022/10/12 12:11

otn

総合スコア80489

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

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

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

このような回答には修正を依頼しましょう。

0

関数自体を変数に入れることができます。
それと同様に、

soup.find_all(has_class_but_no_id)

は、
soup.find_allに、has_class_but_no_idという名前の関数を引数に入れて呼び出しています

投稿2022/10/12 09:50

y_waiwai

総合スコア86062

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

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

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

このような回答には修正を依頼しましょう。

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

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

スクレイピング

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

Beautiful Soup

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。