Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

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のデータを取得するとなると最終的にかかる時間の差が顕著に現れる。

おわり

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした