Beautiful Soup は Python のライブラリで、主な機能は Web ページからデータを取得することです。次の記事では、主に Python クローラーの HTML テキスト解析ライブラリである BeautifulSoup の関連情報を紹介します。記事内の紹介は非常に詳細であり、必要な方は以下を参照してください。
前書き
Python クローラー シリーズの 3 番目の記事では、データの返されるようにリクエストした後、ターゲット データを抽出する必要があります。通常、さまざまな Web サイトから返されるコンテンツにはさまざまな種類があります。 1 つは json 形式で、このタイプのデータは開発者にとって最も使いやすいものです。もう 1 つの XML 形式であり、最も一般的な形式は HTML ドキュメントです。今日は、HTML
から興味深いデータを抽出する方法について説明します。それを解析するための独自の HTML パーサーを作成しますか?それとも正規表現を使用しますか?これらはどれも最善の解決策ではありませんが、Python コミュニティにはこの問題に対する非常に成熟した解決策がすでにあります。BeautifulSoup は HTML ドキュメントの操作に焦点を当てており、その名前は同じ曲に由来しています。ルイス・キャロルの詩による名前。
BeautifulSoup は、HTML ドキュメントを解析するための Python ライブラリです。BeautifulSoup を使用すると、非常に少ないコードで HTML 内のあらゆる興味深いコンテンツを抽出できます。さらに、不完全な形式の HTML ドキュメントも正しく処理できます。
BeautifulSoupをインストール
pip install beautifulsoup4
BeautifulSoup3はメンテナンスのため正式に廃止されました。最新バージョンのBeautifulSoup4をダウンロードする必要があります。
HTML タグ
BeautifulSoup4 を学習する前に、HTML ドキュメントの基本を理解する必要があります。次のコードは、HTML がツリー構造であることを示しています。
<html> <head> <title>hello, world</title> </head> <body> <h1>BeautifulSoup</h1> <p>如何使用BeautifulSoup</p> <body> </html>
html、head、titleなどの多くのタグ(Tag)で構成されており、すべてタグです
タグペアは、次のようなノードを構成します... ルートノードです
ノードの1つ それらの間には特定の関係があります。たとえば、h1とpは互いに隣接しており、隣接する兄弟ノードです
h1はbodyの直接の子ノード、またはhtmlの子孫ノードです
bodyはpの親ノード、htmlはpの祖先ノードです
タグの間にネストされた文字列は、そのノードの下にある特別な子ノード、例えば「hello,world」もノードですが、名前なしで。
BeautifulSoup の使用
BeautifulSoup オブジェクトの構築には 2 つのパラメータが必要です。最初のパラメータは解析する HTML テキスト文字列で、2 番目のパラメータは HTML の解析に使用するパーサーを BeautifulSoup に指示します。
パーサーは HTML を関連オブジェクトに解析する役割を果たし、BeautifulSoup はデータの操作 (追加、削除、変更、チェック) を担当します。 「html.parser」は Python の組み込みパーサーで、「lxml」は C 言語に基づいて開発されたパーサーです。実行には高速ですが、BeautifulSoup オブジェクトを通じて HTML を見つけることができます。
from bs4 import BeautifulSoup text = """ <html> <head> <title >hello, world</title> </head> <body> <h1>BeautifulSoup</h1> <p class="bold">如何使用BeautifulSoup</p> <p class="big" id="key1"> 第二个p标签</p> <a href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a> </body> </html> """ soup = BeautifulSoup(text, "html.parser") # title 标签 >>> soup.title <title>hello, world</title> # p 标签 >>> soup.p <p class="bold">\u5982\u4f55\u4f7f\u7528BeautifulSoup</p> # p 标签的内容 >>> soup.p.string u'\u5982\u4f55\u4f7f\u7528BeautifulSoup'
BeatifulSoup は、HTML を 4 つの主要な
データ型、つまり Tag、NavigableString、BeautifulSoup、Comment に抽象化します。各タグ ノードは Tag オブジェクトであり、通常、BeautifulSoup オブジェクトでラップされた文字列が HTML ドキュメント全体を表します。例: >>> type(soup)
<class 'bs4.BeautifulSoup'>
>>> type(soup.h1)
<class 'bs4.element.Tag'>
>>> type(soup.p.string)
<class 'bs4.element.NavigableString'>
Tag 各タグには名前があり、HTML タグ名に対応します。
>>> soup.h1.name u'h1' >>> soup.p.name u'p'
>>> soup.p['class'] [u'bold']
NavigableString タグ内のコンテンツを取得するには、 を使用します。これは、Unicode 文字列に明示的に変換できる NavigableString オブジェクトです。
>>> soup.p.string u'\u5982\u4f55\u4f7f\u7528BeautifulSoup' >>> type(soup.p.string) <class 'bs4.element.NavigableString'> >>> unicode_str = unicode(soup.p.string) >>> unicode_str u'\u5982\u4f55\u4f7f\u7528BeautifulSoup'
ドキュメント ツリーのトラバースは、その名前が示すように、ルート ノードの HTML タグから開始され、ターゲット要素が見つかるまでトラバースされます。 for はドキュメントの最後にあるため、それを見つけるにはドキュメント全体を走査する必要があり、時間がかかります。したがって、2番目の方法と連携する必要があります。
ドキュメント ツリーを走査することによるタグ ノードの取得は、.tag 名を通じて直接取得できます。例:body タグの取得:
>>> soup.body <body>\n<h1>BeautifulSoup</h1>\n<p class="bold">\u5982\u4f55\u4f7f\u7528BeautifulSoup</p>\n</body>
获取 p 标签
>>> soup.body.p <p class="bold">\u5982\u4f55\u4f7f\u7528BeautifulSoup</p>
获取 p 标签的内容
>>> soup.body.p.string \u5982\u4f55\u4f7f\u7528BeautifulSoup
前面说了,内容也是一个节点,这里就可以用 .string 的方式得到。遍历文档树的另一个缺点是只能获取到与之匹配的第一个子节点,例如,如果有两个相邻的 p 标签时,第二个标签就没法通过 .p 的方式获取,这是需要借用 next_sibling 属性获取相邻且在后面的节点。此外,还有很多不怎么常用的属性,比如:.contents 获取所有子节点,.parent 获取父节点,更多的参考请查看官方文档。
搜索文档树
搜索文档树是通过指定标签名来搜索元素,另外还可以通过指定标签的属性值来精确定位某个节点元素,最常用的两个方法就是 find 和 find_all。这两个方法在 BeatifulSoup 和 Tag 对象上都可以被调用。
find_all()
find_all( name , attrs , recursive , text , **kwargs )
find_all 的返回值是一个 Tag 组成的列表,方法调用非常灵活,所有的参数都是可选的。
第一个参数 name 是标签节点的名字。
# 找到所有标签名为title的节点 >>> soup.find_all("title") [<title>hello, world</title>] >>> soup.find_all("p") [<p class="bold">\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup</p>, <p class="big"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]
第二个参数是标签的class属性值
# 找到所有class属性为big的p标签 >>> soup.find_all("p", "big") [<p class="big"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]
等效于
>>> soup.find_all("p", class_="big") [<p class="big"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]
因为 class 是 Python 关键字,所以这里指定为 class_。
kwargs 是标签的属性名值对,例如:查找有href属性值为 "http://foofish.net" 的标签
>>> soup.find_all(href="foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" ) [<a href="foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]
当然,它还支持正则表达式
>>> import re >>> soup.find_all(href=re.compile("^http")) [<a href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]
属性除了可以是具体的值、正则表达式之外,它还可以是一个布尔值(True/Flase),表示有属性或者没有该属性。
>>> soup.find_all(id="key1") [<p class="big" id="key1"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>] >>> soup.find_all(id=True) [<p class="big" id="key1"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]
遍历和搜索相结合查找,先定位到 body 标签,缩小搜索范围,再从 body 中找 a 标签。
>>> body_tag = soup.body >>> body_tag.find_all("a") [<a href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]
find()
find 方法跟 find_all 类似,唯一不同的地方是,它返回的单个 Tag 对象而非列表,如果没找到匹配的节点则返回 None。如果匹配多个 Tag,只返回第0个。
>>> body_tag.find("a") <a href="foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a> >>> body_tag.find("p") <p class="bold">\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup</p>
get_text()
获取标签里面内容,除了可以使用 .string 之外,还可以使用 get_text 方法,不同的地方在于前者返回的一个 NavigableString 对象,后者返回的是 unicode 类型的字符串。
>>> p1 = body_tag.find('p').get_text() >>> type(p1) <type 'unicode'> >>> p1 u'\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup' >>> p2 = body_tag.find("p").string >>> type(p2) <class 'bs4.element.NavigableString'> >>> p2 u'\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup' >>>
实际场景中我们一般使用 get_text 方法获取标签中的内容。
总结
BeatifulSoup 是一个用于操作 HTML 文档的 Python 库,初始化 BeatifulSoup 时,需要指定 HTML 文档字符串和具体的解析器。BeatifulSoup 有3类常用的数据类型,分别是 Tag、NavigableString、和 BeautifulSoup。查找 HTML元素有两种方式,分别是遍历文档树和搜索文档树,通常快速获取数据需要二者结合。
【相关推荐】
2. python爬虫入门(3)--利用requests构建知乎API
3. python爬虫入门(2)--HTTP库requests
以上がPythonクローラー入門(4) -- HTMLテキスト解析ライブラリBeautifulSoupの詳細解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。