web-dev-qa-db-ja.com

lxmlをデフォルトのBeautifulSoupパーサーとして設定する

私はWebスクレイピングプロジェクトに取り組んでいて、速度の問題に遭遇しました。それを修正するために、BeautifulSoupのパーサーとしてhtml.parserではなくlxmlを使用したいと思います。私はこれを行うことができました:

soup = bs4.BeautifulSoup(html, 'lxml')

しかし、BeautifulSoupを呼び出すたびに'lxml'を繰り返し入力する必要はありません。プログラムの最初に一度使用するパーサーを設定する方法はありますか?

19
Adam Hammes

使用するパーサーの指定 ドキュメントページによると:

BeautifulSoupコンストラクターの最初の引数は、文字列または開いているファイルハンドル(解析するマークアップ)です。 2番目の引数は、マークアップを解析する方法です。

何も指定しないと、インストールされている最適なHTMLパーサーが得られます。 Beautiful Soupは、lxmlのパーサーを最高、次にhtml5libのパーサー、次にPythonの組み込みパーサーの順にランク付けします。

言い換えると、lxmlを同じpython環境にインストールするだけで、デフォルトのパーサーになります。

ただし、パーサーを明示的に記述することはベストプラクティスアプローチと見なされます。 パーサー間の違い があります。これは、BeautifulSoupに最適なパーサーを単独で選択させるとデバッグが困難になるような微妙なエラーを引き起こす可能性があります。 lxmlをインストールする必要があることも覚えておく必要があります。そして、それがインストールされていない場合は、それに気づくことすらありません-BeautifulSoupは、エラーをスローすることなく、次に利用可能なパーサーを取得するだけです。

それでもパーサーを明示的に指定したくない場合は、少なくとも自分自身またはプロジェクトのREADME/documentationに記述したコードを使用する他の人のためにメモし、プロジェクトにlxmlをリストします。 beautifulsoup4とともに要件。

その他: "明示的は暗黙的よりも優れています。"

16
alecxe

明らかに最初に 受け入れられた答え を見てください。それはかなり良いです、そしてこの専門性に関しては:

しかし、BeautifulSoupを呼び出すたびに 'lxml'を繰り返し入力する必要はありません。プログラムの最初に一度使用するパーサーを設定する方法はありますか?

私があなたの質問を正しく理解した場合、いくつかのキーストロークを節約する2つのアプローチを考えることができます。-ラッパー関数を定義するか、-部分的な関数を作成します。

# V1 - define a wrapper function - most straight-forward.
import bs4

def bs_parse(html):
    return bs4.BeautifulSoup(html, 'lxml')
# ...
html = ...
bs_parse(html)

または自慢したい場合は...

import bs4
from functools import partial
bs_parse = partial(bs4.BeautifulSoup, features='lxml')
# ...
html = ...
bs_parse(html)
8
Leonid