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

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

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

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

Beautiful Soup

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

Python

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

Q&A

解決済

4回答

744閲覧

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

KimuraSouki

総合スコア1

スクレイピング

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

Beautiful Soup

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

Python

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

0グッド

1クリップ

投稿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の中身を使えているのはどういった仕組みだからでしょうか。

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

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

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

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

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

guest

回答4

0

以下のプログラムを実行すると 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

総合スコア5406

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

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

0

ベストアンサー

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

総合スコア1579

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

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

KimuraSouki

2022/10/24 23:03

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

0

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

Python

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

投稿2022/10/12 12:11

otn

総合スコア84557

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

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

0

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

soup.find_all(has_class_but_no_id)

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

投稿2022/10/12 09:50

y_waiwai

総合スコア87774

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問