python - более быстрая загрузка ~ 500 веб-страниц (цикл) - PullRequest
3 голосов
/ 02 августа 2011

Для начала я новичок в python, поэтому мой код ниже может быть не самым чистым. Для программы мне нужно скачать около 500 веб-страниц. URL-адреса хранятся в массиве, который заполняется предыдущей функцией. Часть загрузки выглядит примерно так:

def downloadpages(num):

    import urllib
    for i in range(0,numPlanets):
            urllib.urlretrieve(downloadlist[i], 'webpages/'+names[i]'.htm')

каждый файл занимает всего около 20 КБ, но для их загрузки требуется не менее 10 минут. Загрузка одного файла с общим объединенным размером должна занимать всего минуту или две. Есть ли способ, которым я могу ускорить это? Спасибо

Редактировать: Для всех, кто заинтересован, следуя примеру на http://code.google.com/p/workerpool/wiki/MassDownloader и используя 50 потоков, время загрузки было сокращено примерно до 20 секунд с первоначальных 10 минут плюс. Скорость загрузки продолжает уменьшаться, так как потоки увеличиваются примерно до 60 потоков, после чего время загрузки снова начинает увеличиваться.

Ответы [ 4 ]

4 голосов
/ 02 августа 2011

Но вы не скачиваете ни одного файла здесь. Вы загружаете 500 отдельных страниц, каждое соединение связано с накладными расходами (для начального соединения), а также с тем, что делает сервер (обслуживает ли он других людей).

В любом случае загрузка 500 x 20 КБ - это не то же самое, что загрузка одного файла такого размера.

3 голосов
/ 02 августа 2011

Вы можете значительно ускорить выполнение, используя потоки (но будьте осторожны, чтобы не перегружать сервер).

Вступительный материал / Образцы кодов:

2 голосов
/ 02 августа 2011

Для этого можно использовать гринлет.

E.G с eventlet lib:

urls = [url1, url2, ...]

import eventlet
from eventlet.green import urllib2

def fetch(url):
  return urllib2.urlopen(url).read()

pool = eventlet.GreenPool()

for body in pool.imap(fetch, urls):
  print "got body", len(body)

Все звонки в пулах будут псевдо-одновременными.

Конечно, вы должны установить eventlet с помощью pip или easy_install раньше.

У вас есть несколько реализаций гринлетов в Python. Вы можете сделать то же самое с Gevent или другим.

0 голосов
/ 02 августа 2011

Помимо использования какого-либо параллелизма, убедитесь, что любой метод, который вы используете для выполнения запросов, использует постоянство соединения HTTP 1.1. Это позволит каждому потоку открывать только одно соединение и запрашивать все страницы через него, вместо того, чтобы устанавливать / разрывать TCP / IP для каждого запроса. Не уверен, что urllib2 делает это по умолчанию; вам, возможно, придется свернуть свой собственный.

...