Python
クローラー

PythonでWebからバイナリデータをダウンロードする時の速度の話

はじめに

Pythonでバイナリデータをダウンロードする際の速度について検証してみる。
Webクローラーを作成する場合はこの辺の速度は気になるところである。
普通にやるとこんな感じになると思う。

url = "https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles4.xml-p3093314p3698714.bz2"
r = requests.get(url)
with open('{}'.format(url.split('/')[-1]), 'wb') as f:
     f.write(r.content)

もちろんこれでもいいのだが、高速になるならそれに越したことはない。

検証方法

・requests+open
・wget
・curl
・aria2c
これらのダウンローダーをPythonから使用してベンチマークテストを行った。
requests+open以外はsubprocessから使用する。

使用したデータはWikipediaのダンプデータ
データサイズは230MB程度で特別大きいわけではないが自分が作成するWebクローラーでこれ以上大きなサイズのデータを継続的に取得する機会がないという理由でこれくらいが妥当と判断した。

実装

並列処理をすることで実行環境(回線状況等)の差をなるべく減らすようにしたがどの程度効果があるのかは不明である。

import time
import requests
import subprocess
import multiprocessing
from functools import wraps


def func_time(func):
    @wraps(func)
    def wrapper(*args, **kargs):
        start = time.time()
        func(*args, **kargs)
        elapsed = time.time() - start
        print("{0}は{1}秒かかりました".format(func.__name__, elapsed))
    return wrapper


@func_time
def open_time(url):
    r = requests.get(url)
    with open('{}'.format(url.split('/')[-1]), 'wb') as f:
        f.write(r.content)


@func_time
def wget_time(url):
    cmd = "wget -O {0} {1}".format(url.split('/')[-1], url)
    subprocess.call(cmd, shell=True)


@func_time
def curl_time(url):
    cmd = "curl -o {0} {1}".format(url.split('/')[-1], url)
    subprocess.call(cmd, shell=True)


@func_time
def aria2c_time(url):
    cmd = "aria2c -x5 -o {0} {1}".format(url.split('/')[-1], url)
    subprocess.call(cmd, shell=True)


if __name__ == '__main__':
    url = "https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles4.xml-p3093314p3698714.bz2"
    jobs = []
    functions = [open_time, aria2c_time, curl_time, wget_time]
    for func in functions:
        p = multiprocessing.Process(target=func, args=(url,))
        jobs.append(p)
        p.start()
    for job in jobs:
        job.join()
    print('Finish')

結果

aria2c_timeは70.89129710197449秒かかりました
curl_timeは159.21841287612915秒かかりました
wget_timeは173.54129314422607秒かかりました
open_timeは191.10524821281433秒かかりました

まとめ

aria2cが圧倒的に速いという結果になった。
この記事でも紹介されているようにaria2cはwgetやcurlより高速なダウンロードツールである。
とくに懸念がなければダウンロードにはaria2cを使えばいいのではないかと思う。
そしてサイズの大きいデータをダウンロードする際はrequests+openは避けたほうがよさそうである。
1個だけならまだしも100や1000のデータを取得するとなると最終的にかかる時間の差が顕著に現れる。

おわり