Wget Vs urlretrieve из Python - PullRequest
       40

Wget Vs urlretrieve из Python

9 голосов
/ 10 июня 2009

У меня есть задача загрузить ГБс данных с веб-сайта. Данные представлены в виде файлов .gz, каждый файл имеет размер 45 МБ.

Самый простой способ получить файлы - использовать "wget ​​-r -np -A files url". Это позволит загружать данные в рекурсивном формате и отображать веб-сайт. Скорость загрузки очень высокая 4 МБ / с.

Но, просто чтобы поиграть, я также использовал python для сборки своего urlparser.

Загрузка через urlretrieve Python очень медленная, возможно в 4 раза медленнее, чем wget. Скорость загрузки составляет 500 Кб / с. Я использую HTMLParser для анализа тегов href.

Я не уверен, почему это происходит. Есть ли для этого какие-либо настройки.

Спасибо

Ответы [ 10 ]

40 голосов
/ 10 июня 2009

Вероятно, математическая ошибка с вашей стороны.

Просто заметив, что 500 КБ / с (килобайт) равно 4 МБ / с (мегабит) .

9 голосов
/ 05 января 2010

urllib работает для меня так же быстро, как и wget. попробуйте этот код. он показывает прогресс в процентах так же, как wget.

import sys, urllib
def reporthook(a,b,c): 
    # ',' at the end of the line is important!
    print "% 3.1f%% of %d bytes\r" % (min(100, float(a * b) / c * 100), c),
    #you can also use sys.stdout.write
    #sys.stdout.write("\r% 3.1f%% of %d bytes" 
    #                 % (min(100, float(a * b) / c * 100), c)
    sys.stdout.flush()
for url in sys.argv[1:]:
     i = url.rfind('/')
     file = url[i+1:]
     print url, "->", file
     urllib.urlretrieve(url, file, reporthook)
3 голосов
/ 11 июня 2009

Скорости передачи могут легко ввести в заблуждение. Не могли бы вы попробовать следующий скрипт, который просто загружает один и тот же URL как с wget, так и urllib.urlretrieve - запустите его несколько раз, если вы находитесь за прокси-сервером, который кэширует URL со второй попытки.

Для небольших файлов wget займет немного больше времени из-за времени запуска внешнего процесса, но для более крупных файлов это не имеет значения.

from time import time
import urllib
import subprocess

target = "http://example.com" # change this to a more useful URL

wget_start = time()

proc = subprocess.Popen(["wget", target])
proc.communicate()

wget_end = time()


url_start = time()
urllib.urlretrieve(target)
url_end = time()

print "wget -> %s" % (wget_end - wget_start)
print "urllib.urlretrieve -> %s"  % (url_end - url_start)
3 голосов
/ 10 июня 2009

Что касается разбора html, самый быстрый / простой способ, который вы, вероятно, получите, это использование lxml Что касается самих запросов http: httplib2 очень прост в использовании и, возможно, может ускорить загрузку, поскольку он поддерживает соединения поддержки активности HTTP 1.1 и сжатие gzip. Существует также pycURL , который утверждает, что он очень быстрый (но более сложный в использовании) и построен на curllib, но я никогда не использовал его.

Вы также можете попытаться одновременно загружать разные файлы, но также помните, что слишком быстрая попытка оптимизировать время загрузки может быть не слишком вежливой по отношению к рассматриваемому веб-сайту.

Извините за отсутствие гиперссылок, но SO говорит мне: "Извините, новые пользователи могут публиковать не более одной гиперссылки"

1 голос
/ 16 октября 2011

Поскольку python предлагает использовать urllib2 вместо urllib, я беру тест между urllib2.urlopen и wget.

В результате, для загрузки одного и того же файла им обоим требуется почти одинаковое время. Иногда urllib2 работает даже лучше.

Преимущество wget заключается в динамическом индикаторе выполнения, показывающем процент завершенных операций и текущую скорость загрузки при передаче.

Размер файла в моем тесте - 5MB. Я не использовал ни одного модуля кэша в python, и я не знаю, как работает wget при загрузке файла большого размера.

1 голос
/ 10 июня 2009
import subprocess

myurl = 'http://some_server/data/'
subprocess.call(["wget", "-r", "-np", "-A", "files", myurl])
1 голос
/ 10 июня 2009

Может быть, вы можете wget и затем проверить данные в Python?

0 голосов
/ 28 февраля 2010

Вы можете использовать wget -k, чтобы задействовать относительные ссылки во всех URL.

0 голосов
/ 10 июня 2009

Пожалуйста, покажите нам код. Я почти уверен, что это должно быть с кодом, а не с urlretrieve.

Я работал с ним в прошлом, и у меня никогда не было проблем, связанных со скоростью.

0 голосов
/ 10 июня 2009

Разницы не должно быть на самом деле. Все, что делает urlretrieve - это делает простой HTTP-запрос GET. Вы взяли код обработки данных и провели прямое сравнение пропускной способности wget и чистого питона?

...