Python создает рабочие очереди - PullRequest
2 голосов
/ 19 февраля 2012

Я использую данные для веб-сайта, используя Beautiful Soup . Первая страница - это карта Scoutmob , где я беру каждый город, открываю страницу и беру URL каждой сделки в этом городе.

В настоящее время я не использую потоки, и все обрабатывается последовательно. Примерно для всех 500 сделок (из всех городов) моя программа в настоящее время занимает около 400 секунд.

На практике я хотел изменить свой код для использования потоков. Я прочитал несколько учебных пособий и примеров о том, как создавать очереди в Python, но я не хочу создавать 500 потоков для обработки 500 URL-адресов.

Вместо этого я хочу создать около 20 (рабочих) потоков для обработки всех URL-адресов. Может кто-нибудь показать мне пример того, как 20 потоков могут обрабатывать 500 URL в очереди?

Я хочу, чтобы каждый работник извлекал необработанный URL-адрес из очереди, а данные, а затем обработанные данные, работают с другим необработанным URL-адресом. Каждый работник завершает работу только тогда, когда в очереди больше нет URL-адресов.

Между прочим, в то время как каждый работник занимается добычей данных, он также записывает содержимое в базу данных. Так что могут быть проблемы с многопоточностью в базе данных, но это другой вопрос для другого дня :-).

Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 19 февраля 2012

Для вашего примера создание рабочих очередей, вероятно, излишне. Возможно, вам повезет больше, если вы возьмете RSS-ленту, опубликованную для каждой из страниц, вместо того, чтобы пытаться анализировать HTML, который работает медленнее. Ниже я собрал небольшой быстрый скрипт, который анализирует его в общей сложности ~ 13 секунд ... ~ 8 секунд, чтобы захватить города, и ~ 5 секунд, чтобы проанализировать все каналы RSS.

В сегодняшнем запуске он захватил 310 полных сделок из 13 городов (всего перечислено 20 городов, но 7 из них указаны как "скоро").

#!/usr/bin/env python

from lxml import etree, html
from urlparse import urljoin
import time

t = time.time()
base = 'http://scoutmob.com/'
main = html.parse(base)
cities = [x.split('?')[0] for x in main.xpath("//a[starts-with(@class, 'cities-')]/@href")]
urls = [urljoin(base, x + '/today') for x in cities]
docs = [html.parse(url) for url in urls]
feeds = [doc.xpath("//link[@rel='alternate']/@href")[0] for doc in docs]
# filter out the "coming soon" feeds
feeds = [x for x in feeds if x != 'http://feeds.feedburner.com/scoutmob']
print time.time() - t
print len(cities), cities
print len(feeds), feeds

t = time.time()
items = [etree.parse(x).xpath("//item") for x in feeds]
print time.time() - t
count = sum(map(len, items))
print count

Выходные данные:

7.79690480232
20 ['/atlanta', '/new-york', '/san-francisco', '/washington-dc', '/charlotte', '/miami', '/philadelphia', '/houston', '/minneapolis', '/phoenix', '/san-diego', '/nashville', '/austin', '/boston', '/chicago', '/dallas', '/denver', '/los-angeles', '/seattle', '/portland']
13 ['http://feeds.feedburner.com/scoutmob/atl', 'http://feeds.feedburner.com/scoutmob/nyc', 'http://feeds.feedburner.com/scoutmob/sf', 'http://scoutmob.com/washington-dc.rss', 'http://scoutmob.com/nashville.rss', 'http://scoutmob.com/austin.rss', 'http://scoutmob.com/boston.rss', 'http://scoutmob.com/chicago.rss', 'http://scoutmob.com/dallas.rss', 'http://scoutmob.com/denver.rss', 'http://scoutmob.com/los-angeles.rss', 'http://scoutmob.com/seattle.rss', 'http://scoutmob.com/portland.rss']
4.76977992058
310
0 голосов
/ 19 февраля 2012

Просто реализуй это. Вы в значительной степени обговорили ответ прямо здесь

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...