概要
BeautifulSoup で大量の HTML を解析する際の高速化方法について紹介します。
結論
先に結論を書くと、以下の2点が高速化に寄与しました。
- HTML パーサーを標準のものから
lxml
に変更する。(pip install lxml
でインストールする必要があります。) futures.ThreadPoolExecutor
で並列実行する。CPU の論理コア数が多いなら効果大。
テスト用の HTML ファイルを用意する。
テスト用に 100kb 規模の HTML ファイルを100ファイル用意しました。
In [1]:
number of files: 100
テキストまたはバイト列での解析速度の違い
BeautifulSoup に与えるデータがテキストまたはバイト列で違いがあるかを検証しました。結果は、大きな違いは見られませんでした。 文字コードが Shift-jis などの場合は検証していないので、また結果が変わってくるかもしれません。
In [2]:
3.37 s ± 12.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [3]:
3.35 s ± 12.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
HTML パーサーでの解析速度の違い
HTML パーサーが標準では、html5.parser
が使用されますが、他に lxml
、html5lib
が使用できます。
これらで違いがあるか検証しました。なお、lxml
、html5lib
は外部ライブラリのため、pip でインストールしておく必要があります。
結果は、html5lib < html.parser (標準) < lxml となりました。解析速度を上げたい場合は lxml
を検討するとよいかもしれません。
In [4]:
3.39 s ± 38.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [5]:
9.74 s ± 1.96 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [6]:
11.3 s ± 9.21 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
並列処理の活用
concurrent.futures
の ProcessPoolExecutor
で解析処理を並列実行することで、実行時間の短縮が期待できます。
GIL の影響か ThreadPoolExecutor
では返って遅くなってしまいました。
In [7]:
In [8]:
8.03 s ± 9.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [9]:
873 ms ± 4.86 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
改行やタブを事前に削除する
HTML に含まれる改行やタブを事前に削除しておくことで、HTML のパースが高速化できます。
In [10]:
5.11 s ± 7.99 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [ ]:
コメント