見出し画像

【Python】非同期処理で爆速WEBスクレイピング

Pythonで使える強力な便利機能の一つとして、WEBスクレイピングというものがある。

WEBスクレイピングとは、特定のサイトから必要な情報を自動収集することを指す。WEBスクレイピングは物凄く便利だが、対象サイトが1,000や10,000となってくると、レスポンスが返ってくるまでの待ち時間が長いのが難点。これを解決するのが、非同期処理

まずは、シンプルに書いて時間計測。(ちゃんとデータ取得出来ていると確認できるように、リストにレスポンスの文字数を格納)

import requests

url = 'https://www.〇〇〇.com'
data = []
for i in range(100):
    r = requests.get(url)
    data.append(len(r.content))

これで100回サイト訪問して50秒。手動で訪問すると10分くらいかかりそうって考えたら、かなり時間短縮。
でも、10,000回訪問で5,000秒って考えたら、結構なタイムロス。
そこで非同期処理を使い、レスポンスを待たずにリクエストをどんどん投げる。非同期処理ライブラリは簡単なものから複雑なものまでたくさんあるが、ネットワーク通信が大幅短縮するものはasyncioしかなかった。(threadingやsubprocessも試したけど速度が劇的に改善するわけではなかった)。
書き方は以下の通り。出来るだけシンプルに短く書いたけど、それでも複雑なので、まずはコピペして使ってみるのがオススメ。

import asyncio
import requests

url = 'https://www.〇〇〇.com'

def ex(i):
    r = requests.get(url)
    return len(r.content)

async def handler(loop):
    async def async_ex(i):
        async with asyncio.Semaphore(20):
            return await loop.run_in_executor(None, ex, i)
    tasks = [async_ex(i) for i in range(100)]
    return await asyncio.gather(*tasks)
loop = asyncio.get_event_loop()
data = loop.run_until_complete(handler(loop))

時間計測した結果、100回サイト訪問して3.5秒
asyncio.SemaPhore(20)の20は、非同期の最大同時処理数を設定している。ここを20にすることで20倍近いパフォーマンスが叩き出せているわけだが、あまり高く設定すると端末に負荷がかかりすぎるので要注意。

当然その分アクセス先のサーバーに負荷がかかるので、スクレイピングは用法・用量を守り、迷惑がかからないような形で使用しましょう。

この記事が参加している募集

私のイチオシ

この記事が気に入ったらサポートをしてみませんか?