Python での Web スクレイピングに Beautiful Soup を使用する: 基本的な知識の探索

PHPz
リリース: 2023-09-02 10:49:02
オリジナル
1250 人が閲覧しました

Python中使用Beautiful Soup进行网页抓取:基础知识探究

前のチュートリアルでは、Requests モジュールを使用して Python 経由で Web ページにアクセスする方法を説明しました。このチュートリアルでは、GET/POST リクエストの作成や、画像や PDF などのコンテンツをプログラムでダウンロードするなどのトピックについて説明します。このチュートリアルに欠けているものの 1 つは、必要な情報を抽出するリクエストを含む、アクセスした Web ページをスクレイピングする方法に関するガイドです。

このチュートリアルでは、HTML ファイルからデータを抽出するための Python ライブラリである Beautiful Soup について学習します。このチュートリアルではライブラリの基本を学習することに重点を置き、次のチュートリアルではより高度なトピックについて説明します。このチュートリアルのすべての例では Beautiful Soup 4 が使用されていることに注意してください。

###インストール###

Beautiful Soup 4 は

pip

を使用してインストールできます。パッケージ名は beautysoup4 です。 Python 2 と Python 3 で動作するはずです。 リーリー pip がシステムにインストールされていない場合は、Beautiful Soup 4 のソース コード tarball を直接ダウンロードし、

setup.py

を使用してインストールできます。 リーリー Beautiful Soup はもともと Python 2 コードとしてパッケージ化されていました。 Python 3 で使用するためにインストールすると、Python 3 コードに自動的に更新されます。パッケージをインストールしない限り、コードは変換されません。以下に、気付く可能性のある一般的なエラーをいくつか示します:

Python 3 で Python 2 バージョンのコードを実行すると、「HTMLParser という名前のモジュールがありません」
    ImportError
  • が表示されます。 Python 2 で Python 3 バージョンのコードを実行すると、「html.parser という名前のモジュールがありません」
  • ImportError
  • が表示されます。
  • 上記のエラーはどちらも、Beautiful Soup をアンインストールして再インストールすることで修正できます。

パーサーのインストール

Beautiful Soup で使用できるさまざまなパーサーの違いについて説明する前に、スープを作成するコードを書いてみましょう。

リーリー

BeautifulSoup

オブジェクトは 2 つのパラメータを受け入れることができます。最初のパラメータは実際のトークンで、2 番目のパラメータは使用するパーサーです。さまざまなパーサーは、html.parser、lxml、および html5lib です。 lxml パーサーには、HTML パーサーと XML パーサーの 2 つのバージョンがあります。

html.parser

は、古いバージョンの Python ではうまく動作しない組み込みパーサーです。次のコマンドを使用して追加のパーサーをインストールできます: リーリー

lxml

パーサーは非常に高速で、指定された HTML をすばやく解析するために使用できます。一方、html5lib パーサーは非常に遅いですが、非常に寛容でもあります。各パーサーの使用例を次に示します: リーリー 上記の例で説明した違いは、無効な HTML を解析する場合にのみ意味を持ちます。ただし、Web 上のほとんどの HTML は不正な形式であるため、これらの違いを理解すると、一部の解析エラーをデバッグしたり、プロジェクトでどのパーサーを使用するかを決定したりするのに役立ちます。一般に、

lxml

パーサーは非常に良い選択です。 美しいスープの中の物体

Beautiful Soup 指定された HTML ドキュメントを Python オブジェクトのツリーに解析します。知っておく必要がある主な Python オブジェクトは、

Tag

NavigableStringBeautifulSoup、および Comment の 4 つです。

Tag

オブジェクトは、ドキュメント内の実際の XML タグまたは HTML タグを参照します。 tag.name を使用してタグの名前にアクセスできます。ラベルの名前を別の名前に設定することもできます。名前の変更は、Beautiful Soup によって生成されたマークアップに表示されます。

tag['class']

tag['id'] をそれぞれ使用して、タグのクラスや ID などのさまざまなプロパティにアクセスできます。 tag.attrs を使用して属性ディクショナリ全体にアクセスすることもできます。ラベルのプロパティを追加、削除、または変更することもできます。要素の class のような属性は複数の値を取ることができ、リストとして保存されます。 タグ内のテキストは、Beautiful Soup に

NavigableString

として保存されます。 replace_with("string") など、タグ内のテキストを置換する便利なメソッドがいくつかあります。 unicode() を使用して、NavigableString を Unicode 文字列に変換することもできます。 Beautiful Soup を使用すると、Web ページのコメントにアクセスすることもできます。これらのコメントは

Comment

オブジェクトとして保存されますが、これも基本的に NavigableString です。

BeautifulSoup

オブジェクトについては、前のセクションですでに学習しました。文書全体を表すために使用されます。これは実際のオブジェクトではないため、名前やプロパティはありません。 タイトル、タイトル、リンクを取得

Beautiful Soup を使用すると、ページ タイトルなどのデータを簡単に抽出できます。 Python に関する Wikipedia ページをスクレイピングしましょう。まず、Web ページにアクセスするには、リクエスト モジュールのチュートリアルに従って次のコードを使用してページ タグを取得する必要があります。

リーリー

スープを作成したので、次のコードを使用して Web ページのタイトルを取得できます:

soup.title
# <title>Python (programming language) - Wikipedia</title>

soup.title.name
# 'title'

soup.title.string
# 'Python (programming language) - Wikipedia'
ログイン後にコピー

您还可以抓取网页以获取其他信息,例如主标题或第一段、它们的类或 id 属性。

soup.h1
# <h1 class="firstHeading" id="firstHeading" lang="en">Python (programming language)</h1>

soup.h1.string
# 'Python (programming language)'

soup.h1['class']
# ['firstHeading']

soup.h1['id']
# 'firstHeading'

soup.h1.attrs
# {'class': ['firstHeading'], 'id': 'firstHeading', 'lang': 'en'}

soup.h1['class'] = 'firstHeading, mainHeading'
soup.h1.string.replace_with("Python - Programming Language")
del soup.h1['lang']
del soup.h1['id']

soup.h1
# <h1 class="firstHeading, mainHeading">Python - Programming Language</h1>
ログイン後にコピー

同样,您可以使用以下代码遍历文档中的所有链接或副标题:

for sub_heading in soup.find_all('h2'):
    print(sub_heading.text)
    
# all the sub-headings like Contents, History[edit]...
ログイン後にコピー

处理多值和重复属性

HTML 文档中的不同元素使用各种属性来实现不同的目的。例如,您可以将 class 或 id 属性添加到样式、组或标识元素。同样,您可以使用数据属性来存储任何附加信息。并非所有属性都可以接受多个值,但有一些可以。 HTML 规范对这些情况有一套明确的规则,Beautiful Soup 试图遵循所有这些规则。但是,它还允许您指定如何处理多值属性返回的数据。该功能是在4.8版本中添加的,因此在使用之前请确保您已经安装了正确的版本。

默认情况下,像 class 这样可以有多个值的属性将返回一个列表,但像 id 这样的属性将返回单个字符串值。您可以在 BeautifulSoup 构造函数中传递名为 multi_valued_attributes 的参数,并将其值设置为 None。这将确保所有属性返回的值都是字符串。

这是一个例子:

from bs4 import BeautifulSoup

markup = '''
<a class="notice light" id="recent-posts" data-links="1 5 20" href="/recent-posts/">Recent Posts</a>
'''

soup = BeautifulSoup(markup, 'html.parser')
print(soup.a['class'])
print(soup.a['id'])
print(soup.a['data-links'] + "\n")
''' 
Output:
['notice', 'light']
recent-posts
1 5 20
'''


soup = BeautifulSoup(markup, 'html.parser', multi_valued_attributes=None)

print(soup.a['class'])
print(soup.a['id'])
print(soup.a['data-links'] + "\n")
'''
Output:
notice light
recent-posts
1 5 20
'''
ログイン後にコピー

无法保证您从不同网站获得的 HTML 始终完全有效。它可能存在许多不同的问题,例如重复的属性。从版本 4.9.1 开始,Beautiful Soup 允许您通过为 on_duplicate_attribute 参数设置值来指定在这种情况下应该执行的操作。不同的解析器以不同的方式处理此问题,您将需要使用内置的 html.parser 来强制执行特定行为。

from bs4 import BeautifulSoup

markup = '''
<a class="notice light" href="/recent-posts/" class="important dark">Recent Posts</a>
'''

soup = BeautifulSoup(markup, 'lxml')
print(soup.a['class'])
# ['notice', 'light']

soup = BeautifulSoup(markup, 'html.parser', on_duplicate_attribute='ignore')
print(soup.a['class'])
# ['notice', 'light']

soup = BeautifulSoup(markup, 'html.parser', on_duplicate_attribute='replace')
print(soup.a['class'])
# ['important', 'dark']
ログイン後にコピー

浏览 DOM

您可以使用常规标签名称在 DOM 树中导航。链接这些标签名称可以帮助您更深入地导航树。例如,您可以使用 soup.p.a 获取给定维基百科页面第一段中的第一个链接。第一段中的所有链接都可以使用 soup.p.find_all('a') 访问。

您还可以使用 tag.contents 以列表形式访问标记的所有子级。要获取特定索引处的子项,您可以使用 tag.contents[index]。您还可以使用 .children 属性来迭代标记的子级。

仅当您想要访问标记的直接或第一级后代时,.children.contents 才有用。要获取所有后代,您可以使用 .descendants 属性。

print(soup.p.contents)
# [<b>Python</b>, ' is a widely used ',.....the full list]

print(soup.p.contents[10])
# <a href="/wiki/Readability" title="Readability">readability</a>

for child in soup.p.children:
    print(child.name)
# b
# None
# a
# None
# a
# None
# ... and so on.
ログイン後にコピー

您还可以使用 .parent 属性访问元素的父元素。同样,您可以使用 .parents 属性访问元素的所有祖先。顶级 <html> 标签的父级是 BeautifulSoup 对象本身,其父级为 None。

print(soup.p.parent.name)
# div

for parent in soup.p.parents:
    print(parent.name)
# div
# div
# div
# body
# html
# [document]
ログイン後にコピー

您可以使用 .previous_sibling.next_sibling 属性访问元素的上一个和下一个同级元素。

要使两个元素成为兄弟元素,它们应该具有相同的父元素。这意味着元素的第一个子元素不会有前一个同级元素。类似地,元素的最后一个子元素不会有下一个同级元素。在实际的网页中,元素的上一个和下一个同级元素很可能是换行符。

您还可以使用 .previous_siblings.next_siblings 迭代元素的所有同级元素。

soup.head.next_sibling
# '\n'

soup.p.a.next_sibling
# ' for '

soup.p.a.previous_sibling
# ' is a widely used '

print(soup.p.b.previous_sibling)
# None
ログイン後にコピー

您可以使用 .next_element 属性转到紧随当前元素之后的元素。要访问紧邻当前元素之前的元素,请使用 .previous_element 属性。

同样,您可以分别使用 .previous_elements.next_elements 迭代当前元素之前和之后的所有元素。

仅解析文档的一部分

假设您在查找特定内容时需要处理大量数据,并且节省一些处理时间或内存对您来说很重要。在这种情况下,您可以利用 Beautiful Soup 中的 SoupStrainer 类。此类允许您仅关注特定元素,而忽略文档的其余部分。例如,您可以通过在 SoupStrainer 构造函数中传递适当的选择器,使用它来忽略网页上除图像之外的所有其他内容。

请记住,汤过滤器不能与 html5lib 解析器一起使用。但是,您可以将其与 lxml 和内置解析器一起使用。下面是一个示例,我们解析美国的维基百科页面并获取类为 thumbimage 的所有图像。

import requests
from bs4 import BeautifulSoup, SoupStrainer

req = requests.get('https://en.wikipedia.org/wiki/United_States')

thumb_images = SoupStrainer(class_="thumbimage")

soup = BeautifulSoup(req.text, "lxml", parse_only=thumb_images)

for image in soup.find_all("img"):
    print(image['src'])
'''
Output:
//upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Mesa_Verde_National_Park_-_Cliff_Palace.jpg/220px-Mesa_Verde_National_Park_-_Cliff_Palace.jpg
//upload.wikimedia.org/wikipedia/commons/thumb/3/38/Map_of_territorial_growth_1775.svg/260px-Map_of_territorial_growth_1775.svg.png
//upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Declaration_of_Independence_%281819%29%2C_by_John_Trumbull.jpg/220px-Declaration_of_Independence_%281819%29%2C_by_John_Trumbull.jpg
//upload.wikimedia.org/wikipedia/commons/thumb/9/94/U.S._Territorial_Acquisitions.png/310px-U.S._Territorial_Acquisitions.png
...and many more images
'''
ログイン後にコピー

您应该注意,我使用 class_ 而不是 class 来获取这些元素,因为 class 是 Python 中的保留关键字。

最终想法

完成本教程后,您现在应该能够很好地理解不同 HTML 解析器之间的主要差异。您现在还应该能够浏览网页并提取重要数据。当您想要分析给定网站上的所有标题或链接时,这会很有帮助。

在本系列的下一部分中,您将学习如何使用 Beautiful Soup 库来搜索和修改 DOM。

以上がPython での Web スクレイピングに Beautiful Soup を使用する: 基本的な知識の探索の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート