ホームページ  >  記事  >  バックエンド開発  >  クローラ解析手法2:Beautifulsoup

クローラ解析手法2:Beautifulsoup

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼転載
2019-06-05 13:25:342359ブラウズ

多くの言語でクロールできますが、Python ベースのクローラーの方が簡潔で便利です。クローラーも Python 言語の重要な部分になっています。クローラーを解析する方法もたくさんあります。

誰もが Requests ライブラリの使い方をマスターしているはずですが、Requests を使用して Web ページの HTML コード情報を取得する場合、どうすれば必要な情報を取得できるでしょうか?文字列の find メソッドやより高度な正規表現など、さまざまな方法を試したことがあると思います。正規表現を使用すると必要な情報を照合できますが、特定の文字列を照合するために正規の照合ルールを何度も試すと、誰もが非常にイライラすることになると思います。

そこで、もっと便利なツールはないものかということになります。答えは「はい」です。BeautifulSoup という強力なツールもあります。これを使用すると、HTML または XML タグ内のコンテンツを簡単に抽出できます。この記事では、BeautifulSoup の一般的なメソッドについて学びましょう。

前回の記事ではクローラー解析手法1:JOSN解析について説明しましたが、今回はBeautifulsoup解析についてご紹介します。

クローラ解析手法2:Beautifulsoup


#BeautifulSoup とは何ですか?

Python の Web ページの解析は正規表現を使用して完了できます。そのため、コードを記述する際には、コードを 1 つずつ照合する必要があり、一致ルールも記述する必要があります。全体の実装は非常に複雑です。 。 BeautifulSoup に関しては、効率的な処理を備えた便利な Web ページ解析ライブラリであり、複数のパーサーをサポートしています。ほとんどの場合、正規表現を記述せずに、これを使用して Web ページの情報を簡単に抽出できます。

公式ドキュメント

インストール: $ pip install beautifulsoup4

BeautifulSoup は、多くのパーサーをサポートする Web ページ解析ライブラリですが、最も主流なものは 2 つあります。 1 つは Python 標準ライブラリで、もう 1 つは lxml HTML パーサーです。この 2 つの使用法は似ています。

from bs4 import BeautifulSoup
 
# Python的标准库
BeautifulSoup(html, 'html.parser')
 
# lxml
BeautifulSoup(html, 'lxml')

Python の組み込み標準ライブラリの実行速度は平均的ですが、Python の以前のバージョンでは、中国語のフォールト トレランスが比較的劣ります。 lxmlHTML パーサーの実行速度は速いですが、C 言語に依存するライブラリのインストールが必要です。

lxml のインストール

lxml のインストールは C 言語ライブラリに依存しているため、Windows に lxml をインストールすると、さまざまな奇妙なエラーが発生します。正常にインストールするには、pip install lxml

を使用することをお勧めします。しかし、ほとんどの人はここで落ちてしまいます。

lxml の .whl ファイルを使用してインストールすることをお勧めします。まず、wheel ライブラリをインストールする必要がありますが、このライブラリを使用する場合のみ、.whl ファイルを正常にインストールできます。 pip install Wheel

公式 Web サイトからシステムと Python のバージョンに一致する lxml ファイルをダウンロードします。

さらに、自分のシステムや Python のバージョン情報を知らない友人。システム管理者ツール (CMD) または Python の IDLE に入り、次のコードを入力する必要があります:

import pip
 
print(pip.pep425tags.get_supported())

この時点で、出力された Python のバージョン情報を確認できます。

lxml ファイルをダウンロードした後、ファイルの場所を見つけて、管理者ツールに入り、pip を使用してインストールする必要があります。 pip install whl ファイルの完全名

インストールが完了したらPython を入力してインポートできます。エラーが報告されなければ、インストールが成功しました。

面倒だと思う友人がいる場合は、anaconda のダウンロード アドレスをインストールすることをお勧めします (インストール速度が遅い場合は、国内のミラーを見つけることができます)。 Windows で pip を使用している場合、インストール エラーの問題はなくなります。


BeautifulSoup の基本的なタグ選択方法

Python の組み込み標準ライブラリ パーサーは悪くありませんが、それでも皆さんにお勧めします.lxml は十分に速いためです。次に、lxml パーサーを使用して次のコードを示します。

まず、公式ドキュメントの例をインポートしましょう:

html_doc = """
<html><head><title>The Dormouse&#39;s story</title></head>
<body>
<p class="title"><b>The Dormouse&#39;s story</b></p>
 
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
 
<p class="story">...</p>
"""

HTML コード。BeautifulSoup オブジェクトを取得し、標準のインデント形式構造に従って出力できます:

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, &#39;lxml&#39;)

上記の HTML コードが不完全であることがわかります。次に、prettify() メソッドを使用して自動補完を実行します。コメント部分は操作の出力です:

print(soup.prettify())
# <html>
#  <head>
#   <title>
#    The Dormouse&#39;s story
#   </title>
#  </head>
#  <body>
#   <p class="title">
#    <b>
#     The Dormouse&#39;s story
#    </b>
#   </p>
#   <p class="story">
#    Once upon a time there were three little sisters; and their names were
#    <a class="sister" href="http://example.com/elsie" id="link1">
#     Elsie
#    </a>
#    ,
#    <a class="sister" href="http://example.com/lacie" id="link2">
#     Lacie
#    </a>
#    and
#    <a class="sister" href="http://example.com/tillie" id="link2">
#     Tillie
#    </a>
#    ; and they lived at the bottom of a well.
#   </p>
#   <p class="story">
#    ...
#   </p>
#  </body>
# </html>

Get tag

print(soup.title)
# <title>The Dormouse&#39;s story</title>

出力結果から、取得したコンテンツの属性 (実際には title タグ) を確認できます。 HTML コード内。

名前の取得

print(soup.title.name)
# &#39;title&#39;

は実際にはラベルの名前です。

属性の取得

print(soup.p.attrs[&#39;class&#39;])
# &#39;title&#39;
 
print(soup.p[&#39;class&#39;])
# &#39;title&#39;

ラベルの属性を取得するには、attrs メソッドを使用し、それに属性名を渡して、ラベルの属性。結果から、pタグの属性名を直接渡すとtag属性も取得できることが分かります。

コンテンツの取得

print(soup.title.string)
# &#39;The Dormouse&#39;s story&#39;

   

我们还可以使用嵌套的选择,比如我们获得body标签里面p标签的内容:

print(soup.body.p.string)
# &#39;The Dormouse&#39;s story&#39;

   

常见用法

标准选择器

虽然BeautifulSoup的基本用法,标签获取,内容获取,可以解析一些 html代码。但是在遇到很多复杂的页面时,上面的方法是完全不足的,或者是很繁琐的,因为有时候有的标签会有几个属性(class、id等)。

索性BeautifulSoup给我们提供了很方便的标准选择器,也就是 API 方法,这里着重介绍2个: find() 和 find_all() 。其它方法的参数和用法类似,大家举一反三吧。

find_all()

find_all(name, attrs, recursive, text, **kwargs)可以根据标签,属性,内容查找文档。
find_all()其实和正则表达式的原理很相似,他能找出所有能满足匹配模式的结果,在把结果以列表的形式返回。
仍然是文档的例子:

html_doc = """
<html><head><title>The Dormouse&#39;s story</title></head>
<body>
<p class="title"><b>The Dormouse&#39;s story</b></p>
 
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
 
<p class="story">...</p>
"""
from bs4 import BeautifulSoup
 
soup = BeautifulSoup(html_doc, 'lxml')

   

过滤器

文档参考
介绍 find_all() 方法前,大家可以参考一下过滤器的类型。过滤器只能作为搜索文档的参数,或者说应该叫参数类型更为贴切。这些过滤器贯穿整个搜索的API。过滤器可以被用在 tag 的name中,节点的属性中,字符串中或他们的混合中。

find_all() 方法搜索当前 tag 的所有 tag 子节点,并判断是否符合过滤器的条件。这里有几个例子:

soup.find_all("title")
# [<title>The Dormouse&#39;s story</title>]
 
soup.find_all("p", "title")
# [<p class="title"><b>The Dormouse&#39;s story</b></p>]
 
soup.find_all("a")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
 
soup.find_all(id="link2")
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

   

有几个方法很相似,还有几个方法是新的,参数中的 string 和id是什么含义? 为什么 find_all("p", "title") 返回的是CSS Class为”title”的标签? 我们来仔细看一下find_all()的参数:

name参数

name 参数可以查找所有名字为 name 的 tag,字符串对象会被自动忽略掉。

soup.find_all("title")
# [The Dormouse&#39;s story]

   

搜索 name 参数的值可以使任一类型的过滤器,字符窜,正则表达式,列表,方法或是True 。
我们常用的 name 参数是搜索文档的标签名。

keyword参数

如果我们的 HTML代码中有几个div标签,但是我们只想获取到class属性为top的div标签,我们怎么出来呢。

soup.find_all(&#39;div&#39;, class_=&#39;top&#39;)

# 这里注意下,class是Python的内部关键词,我们需要在css属性class后面加一个下划线'_',不然会报错。

   

仍然以上面的代码实例:

soup.find_all(&#39;a&#39;, id=&#39;link2&#39;)
# [<a id="link2" href="http://example.com/lacie">Lacie</a>]

   

这样我们就只获取到id为link2的a标签。

limit参数

find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢。如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量。效果与 SQL 中的limit关键字类似,当搜索到的结果数量达到limit的限制时,就停止搜索返回结果。

比如我们要搜索出a标签,但是满足的有3个,我们只想要得到2个:

soup.find_all("a", limit=2)
# [<a id="link1" class="sister" href="http://example.com/elsie">Elsie</a>,
# <a id="link2" class="sister" href="http://example.com/lacie">Lacie</a>]

   

其他的参数,不是经常用到,大家如需了解可以参考官方文档。

find()

find_all()返回的是所有元素列表,find()返回单个元素。

find( name , attrs , recursive , string , **kwargs )

find_all()方法将返回文档中符合条件的所有 tag,尽管有时候我们只想得到一个结果。比如文档中只有一个标签,那么使用find_all()方法来查找标签就不太合适, 使用find_all方法并设置limit=1参数不如直接使用find()方法。下面两行代码是等价的:

soup.find_all(&#39;title&#39;, limit=1)
# [The Dormouse&#39;s story]
 
soup.find(&#39;title&#39;)
#The Dormouse&#39;s story

   

唯一的区别是find_all()方法的返回结果是值包含一个元素的列表,而find()方法直接返回结果。find_all()方法没有找到目标是返回空列表, find()方法找不到目标时,返回None。

CSS选择器

Beautiful Soup支持大部分的 CSS选择器。在Tag或BeautifulSoup对象的.select()方法中传入字符串参数, 即可使用 CSS选择器的语法找到 tag。我们在写 css 时,标签 class类名加”.“,id属性加”#“。

soup.select("title")
# [The Dormouse&#39;s story]

   

通过 tag标签逐层查找:

soup.select("body a")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie"  id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
 
soup.select("html head title")
# [<title>The Dormouse&#39;s story</title>]

   

找到某个 tag标签下的直接子标签:

soup.select("head > title")
# [<title>The Dormouse&#39;s story</title>]
 
soup.select("p > a")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie"  id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
 
soup.select("p > #link1")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
 
soup.select("body > a")
# []

   

通过 CSS 的 class类名查找:

soup.select(".sister")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

   

通过 tag 的 id 查找:

soup.select("#link1")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
 
soup.select("a#link2")
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

   

同时用多种 CSS选择器查询元素,使用逗号隔开:

soup.select("#link1,#link2")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

   

提取标签内容

如果我们得到了几个标签:

list = [<a href="http://www.baidu.com/">百度</a>,
 
<a href="http://www.163.com/">网易</a>,
 
<a href="http://www.sina.com/"新浪</a>]

   

我们要怎样提取他里面的内容呢。我们开始的时候有提及。

for i in list:
    print(i.get_text()) # 我们使用get_text()方法获得标签内容
    print(i.get[&#39;href&#39;] # get[&#39;attrs&#39;]方法获得标签属性
    print(i[&#39;href&#39;]) # 简写结果一样

   

结果:

百度
网易
新浪
http://www.baidu.com/
http://www.163.com/
http://www.sina.com/
http://www.baidu.com/
http://www.163.com/
http://www.sina.com/

   

总结

BeautifulSoup の解析ライブラリです。lxml の使用を推奨します。文字化けが発生する場合は、html.parser を使用できます。BeautifulSoup のタグ選択とフィルタリング方法は弱いですが高速です。find_all()、find() メソッドの使用を推奨します。もちろん、CSS セレクターに精通している場合は、タグを検索するには .select() メソッド、ラベル テキストの内容を取得するには get_text() メソッド、ラベルを取得するには get[attrs] メソッドを使用することをお勧めします。属性値。

以上がクローラ解析手法2:Beautifulsoupの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。