Pythonでスクレイピングを並列処理する

並列処理について調べていたら、スクレイピングはサーバのレスポンス待ちなどでデータ受信に時間がかかるので、並列処理すると効率がよいという話を読んだ。
確かに納得感のある説明だが、実際のところどのくらいの効果があるのか気になり簡単な実験をしてみた。

実験内容

以下の4つのURLをスクレイピングする。

並列処理は組み込みモジュールのmultiprocessingで実行している。実行環境(MacBook Pro 2017モデル)のコア数が4であることから同時処理数は4にした。なおプロセッサは2.3 GHz Intel Core i5、メモリは8GBである。

実験に使ったプログラムは以下にアップロードしてある。Pythonとモジュールのバージョンに関する情報も出力した。
https://github.com/ryo101/blog/blob/master/20220827/scraping_with_multiprocessing.ipynb


スクレイピングと並列処理に関する実装を転記すると、

def get_html(url):
    return requests.get(url)

スクレイピング関数を定義したうえで、

for u in urls:
    htmls.append(get_html(u))

で単一処理を、

p = Pool(multiprocessing.cpu_count())
htmls = p.map(get_html, urls)
p.close()

で並列処理を実行している。

なお、はじめget_html内でhtmlsにappendするように書いたところ、並列処理では結果がhtmlsに入らなかった。
リクエスト結果をget_htmlで返すようにしたら単一処理でも並列処理でもうまくいった。

実験結果

各々10回ずつ実行して得られた実行時間である(単位秒、小数点第2位)。

  • 単一処理:平均0.58、最小0.44、最大0.95
  • 並列処理:平均0.33、最小0.27、最大0.43

URLが4つだけでも、さすがに1/4の実行時間にはならないものの、およそ半分になっている。
4つ程度だと並列のほうが時間がかかるのではと予想していたのでこの結果は意外だった。

スクレイピングの並列処理の実装について検索するともっと凝った実装例も出てくるが、上に載せた書き方だとコード量は単一処理とほぼ変わらないし、これでも十分に時短の効果がある。使える場面では積極的に活用していきたい。