Urllib2 & BeautifulSoup: Хорошая пара, но слишком медленная – urllib3 и темы?

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

Проблема с моим скриптом ниже – время выполнения: так медленно!

Шаг 1 : Я забираю эту страницу http://www.cambridgeesol.org/institutions/results.php?region=Afghanistan&type=&BULATS=on

Шаг 2 : Я просматриваю страницу с помощью BeautifulSoup

Шаг 3: Я помещаю данные в документ excel

Шаг 4: Я делаю это снова и снова, и снова для всех стран в моем списке (большой список) (я просто меняю «Афганистан» в URL-адресе в другую страну)

Вот мой код:

ws = wb.add_sheet("BULATS_IA") #We add a new tab in the excel doc x = 0 # We need x and y for pulling the data into the excel doc y = 0 Countries_List = ['Afghanistan','Albania','Andorra','Argentina','Armenia','Australia','Austria','Azerbaijan','Bahrain','Bangladesh','Belgium','Belize','Bolivia','Bosnia and Herzegovina','Brazil','Brunei Darussalam','Bulgaria','Cameroon','Canada','Central African Republic','Chile','China','Colombia','Costa Rica','Croatia','Cuba','Cyprus','Czech Republic','Denmark','Dominican Republic','Ecuador','Egypt','Eritrea','Estonia','Ethiopia','Faroe Islands','Fiji','Finland','France','French Polynesia','Georgia','Germany','Gibraltar','Greece','Grenada','Hong Kong','Hungary','Iceland','India','Indonesia','Iran','Iraq','Ireland','Israel','Italy','Jamaica','Japan','Jordan','Kazakhstan','Kenya','Kuwait','Latvia','Lebanon','Libya','Liechtenstein','Lithuania','Luxembourg','Macau','Macedonia','Malaysia','Maldives','Malta','Mexico','Monaco','Montenegro','Morocco','Mozambique','Myanmar (Burma)','Nepal','Netherlands','New Caledonia','New Zealand','Nigeria','Norway','Oman','Pakistan','Palestine','Papua New Guinea','Paraguay','Peru','Philippines','Poland','Portugal','Qatar','Romania','Russia','Saudi Arabia','Serbia','Singapore','Slovakia','Slovenia','South Africa','South Korea','Spain','Sri Lanka','Sweden','Switzerland','Syria','Taiwan','Thailand','Trinadad and Tobago','Tunisia','Turkey','Ukraine','United Arab Emirates','United Kingdom','United States','Uruguay','Uzbekistan','Venezuela','Vietnam'] Longueur = len(Countries_List) for Countries in Countries_List: y = 0 htmlSource = urllib.urlopen("http://www.cambridgeesol.org/institutions/results.php?region=%s&type=&BULATS=on" % (Countries)).read() # I am opening the page with the name of the correspondant country in the url s = soup(htmlSource) tableGood = s.findAll('table') try: rows = tableGood[3].findAll('tr') for tr in rows: cols = tr.findAll('td') y = 0 x = x + 1 for td in cols: hum = td.text ws.write(x,y,hum) y = y + 1 wb.save("%s.xls" % name_excel) except (IndexError): pass 

Поэтому я знаю, что все не идеально, но я с нетерпением жду возможности узнать новое в Python! Сценарий очень медленный, потому что urllib2 не так быстро, и BeautifulSoup. Для супа, я думаю, я не могу сделать это лучше, но для urllib2 я этого не делаю.

EDIT 1: Многопроцессорность бесполезна с urllib2? Кажется, интересно в моем случае. Что вы думаете об этом потенциальном решении?

 # Make sure that the queue is thread-safe!! def producer(self): # Only need one producer, although you could have multiple with fh = open('urllist.txt', 'r'): for line in fh: self.queue.enqueue(line.strip()) def consumer(self): # Fire up N of these babies for some speed while True: url = self.queue.dequeue() dh = urllib2.urlopen(url) with fh = open('/dev/null', 'w'): # gotta put it somewhere fh.write(dh.read()) 

EDIT 2: URLLIB3 Может ли кто-нибудь рассказать мне больше об этом?

Повторно используйте одно и то же соединение сокета для нескольких запросов (HTTPConnectionPool и HTTPSConnectionPool) (с дополнительной проверкой сертификата на стороне клиента). https://github.com/shazow/urllib3

Поскольку я запрашиваю 122 раза один и тот же веб-сайт для разных страниц, я думаю, что повторное использование одного и того же сокетного соединения может быть интересным, я ошибаюсь? Не может быть быстрее? …

 http = urllib3.PoolManager() r = http.request('GET', 'http://www.bulats.org') for Pages in Pages_List: r = http.request('GET', 'http://www.bulats.org/agents/find-an-agent?field_continent_tid=All&field_country_tid=All&page=%s' % (Pages)) s = soup(r.data) 

3 Solutions collect form web for “Urllib2 & BeautifulSoup: Хорошая пара, но слишком медленная – urllib3 и темы?”

Подумайте, используя что-то вроде workerpool . Ссылаясь на пример Mass Downloader , в сочетании с urllib3 будет выглядеть примерно так:

 import workerpool import urllib3 URL_LIST = [] # Fill this from somewhere NUM_SOCKETS = 3 NUM_WORKERS = 5 # We want a few more workers than sockets so that they have extra # time to parse things and such. http = urllib3.PoolManager(maxsize=NUM_SOCKETS) workers = workerpool.WorkerPool(size=NUM_WORKERS) class MyJob(workerpool.Job): def __init__(self, url): self.url = url def run(self): r = http.request('GET', self.url) # ... do parsing stuff here for url in URL_LIST: workers.put(MyJob(url)) # Send shutdown jobs to all threads, and wait until all the jobs have been completed # (If you don't do this, the script might hang due to a rogue undead thread.) workers.shutdown() workers.wait() 

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

Отказ от ответственности: я являюсь автором обоих, urllib3 и workerpool.

Я не думаю, что urllib или BeautifulSoup медленны. Я запускаю свой код на своей локальной машине с модифицированной версией (удалял материал excel). Для открытия соединения потребовалось около 100 мс, загрузить контент, проанализировать его и распечатать на консоли для страны.

10 мс – это общая сумма времени, проведенного BeautifulSoup для анализа содержимого, и печать на консоль для каждой страны. Это достаточно быстро.

Я также не верю, что использование Scrappy или Threading решит проблему. Потому что проблема в том, что она будет быстрой.

Добро пожаловать в мир HTTP. Иногда это будет медленным, иногда это будет очень быстро. Пара медленных причин подключения

  • из-за того, что сервер обрабатывает ваш запрос (иногда возвращает 404)
  • Разрешение DNS,
  • HTTP-рукопожатие,
  • стабильность вашего интернет-провайдера,
  • ваша полоса пропускания,
  • скорость потери пакетов

и т.д..

Не забывайте, что вы пытаетесь сделать 121 HTTP-запрос серверу, и вы не знаете, какие у них серверы. Они могут также запретить ваш IP-адрес из-за последовательных вызовов.

Взгляните на Requests lib. Прочтите их документацию. Если вы делаете это, чтобы больше узнать Python, не переходите непосредственно в Scrapy.

Эй, ребята,

Некоторые новости из этой проблемы! Я нашел этот скрипт, который может быть полезен! Я на самом деле тестирую его, и это многообещающе (6.03 для запуска сценария ниже).

Моя идея – найти способ смешать это с urllib3. В effet я делаю запрос на том же хосте много раз.

PoolManager будет заботиться о повторном использовании соединений для вас всякий раз, когда вы запрашиваете тот же хост. это должно охватывать большинство сценариев без значительной потери эффективности, но вы всегда можете опуститься до более низкого уровня компонента для более детального контроля. (сайт urrlib3 doc)

В любом случае, это кажется очень интересным, и если я пока не вижу, как смешивать эти две функциональные функции (urllib3 и сценарий с потоком ниже), я думаю, это выполнимо! 🙂

Большое вам спасибо за то, что нашли время, чтобы дать мне руку с этим, Он хорошо пахнет!

 import Queue import threading import urllib2 import time from bs4 import BeautifulSoup as BeautifulSoup hosts = ["http://www.bulats.org//agents/find-an-agent?field_continent_tid=All&field_country_tid=All", "http://www.bulats.org//agents/find-an-agent?field_continent_tid=All&field_country_tid=All&page=1", "http://www.bulats.org//agents/find-an-agent?field_continent_tid=All&field_country_tid=All&page=2", "http://www.bulats.org//agents/find-an-agent?field_continent_tid=All&field_country_tid=All&page=3", "http://www.bulats.org//agents/find-an-agent?field_continent_tid=All&field_country_tid=All&page=4", "http://www.bulats.org//agents/find-an-agent?field_continent_tid=All&field_country_tid=All&page=5", "http://www.bulats.org//agents/find-an-agent?field_continent_tid=All&field_country_tid=All&page=6"] queue = Queue.Queue() out_queue = Queue.Queue() class ThreadUrl(threading.Thread): """Threaded Url Grab""" def __init__(self, queue, out_queue): threading.Thread.__init__(self) self.queue = queue self.out_queue = out_queue def run(self): while True: #grabs host from queue host = self.queue.get() #grabs urls of hosts and then grabs chunk of webpage url = urllib2.urlopen(host) chunk = url.read() #place chunk into out queue self.out_queue.put(chunk) #signals to queue job is done self.queue.task_done() class DatamineThread(threading.Thread): """Threaded Url Grab""" def __init__(self, out_queue): threading.Thread.__init__(self) self.out_queue = out_queue def run(self): while True: #grabs host from queue chunk = self.out_queue.get() #parse the chunk soup = BeautifulSoup(chunk) #print soup.findAll(['table']) tableau = soup.find('table') rows = tableau.findAll('tr') for tr in rows: cols = tr.findAll('td') for td in cols: texte_bu = td.text texte_bu = texte_bu.encode('utf-8') print texte_bu #signals to queue job is done self.out_queue.task_done() start = time.time() def main(): #spawn a pool of threads, and pass them queue instance for i in range(5): t = ThreadUrl(queue, out_queue) t.setDaemon(True) t.start() #populate queue with data for host in hosts: queue.put(host) for i in range(5): dt = DatamineThread(out_queue) dt.setDaemon(True) dt.start() #wait on the queue until everything has been processed queue.join() out_queue.join() main() print "Elapsed Time: %s" % (time.time() - start) 
  • urllib2 не получает весь HTTP-ответ
  • Загрузка изображения через urllib и python
  • Пакетная загрузка текста и изображений из URL с помощью Python / urllib / beautifulsoup?
  • Как отправить не-ASCII-символы с помощью httplib, когда content-type - "application / xml"
  • Извлечь содержимое статьи новостей из сохраненных .html-страниц
  • Как сделать HTTP-запрос Python с данными POST и Cookie?
  • Как ускорить выбор страниц с urllib2 в python?
  • Автоматизация действий браузера - нажатие на кнопки кнопки «Ошибка» - «Нажмите« Успешно », но« Ошибка загрузки ». ..»
  •  
    Interesting Posts for Van-Lav

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

    суммируя все возможные комбинации произвольного числа массивов и применяя ограничения

    Selenium change firefox браузерный язык python mac

    Программный поиск google в Python с помощью пользовательского поиска

    python: мои классы как ключи dict. как?

    Магический вывод трубки Ipython для переменной?

    Счетчик строк гласных Python

    Типичные соглашения об именах для каталогов Python в пакетах

    Обновление элементов GUI в MultiThreaded PyQT

    Включение элемента в массиве 2d определенного цвета на основе ввода пользователем

    Более эффективные движения, редактирующие файлы python в vim

    Связь с USB-устройством в Python

    Как проверить, является ли каталог вспомогательной директорией другого каталога

    Numpy AttributeError: объект 'float' не имеет атрибута 'exp'

    python parse выводит только первую строку из списка

    Python - лучший язык программирования в мире.