Python и SEO

Multiprocessing

Узнал про модуль spynner, это такой управляемый браузер. Если на страничке много трудноподдающегося JavaScript-а, то вместо urllib2 или curl можно попробовать натравить на него spynner. Основы работы с ним можно почитать здесь. В общем был он нужен мне, но проблема в том, что он достаточно медленный, а работать в несколько потоков с ним не представляется возможным, так он берет своё начало от GUI-класса библиотеки Qt, которые в свою очередь можно использовать только в main-потоке. Поэтому вместо многопоточности пришлось думать о многопроцессовости. Ну это тоже самое если сделать однопоточный скрипт и
запустить одновременно N его копий. Про многопоточность я уже написал один пост, который полностью состоит из быдлокода=) С тех пор, я чутка поумнел и для организации потоков наследуюсь от класса Thread. С многопроцессовостью всё аналогично, только классы другие, а методы и структура вся та же.

# coding: utf8
import spynner
from spynner import browser
import multiprocessing
from multiprocessing import Process

class Serfer(multiprocessing.Process):
    def __init__(self,queue):
        multiprocessing.Process.__init__(self)
        self.__queue = queue # наша очередь заданий
        self.kill_received = False # На всякий случай переменная, вдруг надо будет всё остановить
    def run(self):
        while not self.kill_received:
            try: item = self.__queue.get_nowait() # ждём данные
            except Queue.Empty: break

            error = True
            try: error = self.serfing(item)
            except: traceback.print_exc()

            time.sleep(0.1)
            self.__queue.task_done() # задача завершена
            if error: self.__queue.put(item) # Если была ошибка, то еще раз с этими данными
        return
    def serfing(self,url):

        br = browser.Browser() # запускаем браузер
        br.create_webview()
        br.show() # отображаем
        br.load(url) # загружаем страницу
        br.wait_a_little(75)

        br.destroy_webview()
        br.close() # закрываем браузер

def main():
    queue = multiprocessing.JoinableQueue() # создаем очередь заданий
    processes = 5
    # Урлы по которым надо будет перейти в браузере
    urls = ["http://ya.ru","http://google.ru","http://yahoo.com",
"http://bing.com","http://rambler.ru"]

    for url in urls:
        queue.put(url) # заносим данные в очередь
    for i in xrange(processes):
        t = Serfer(queue) # создаем процесс
        t.start() # стартуем
        time.sleep(0.1)
    queue.join() # приостанавливаем дальнейшее выполнение кода, пока очередь не опустошится
    print "Done"
if __name__ == '__main__':
    main()
 

Автор: kalombo

Сентябрь 29, 2011 в 10:56 пп

Категория GUI,Python

Метки , , ,

Ответы: 8 to 'Multiprocessing'

Подписаться на комментарии RSS or TrackBack to 'Multiprocessing'.

  1. Отличный пример! Добавил в свою копилку.

    Мультипроцессинг выглядит также, как и мультитреадинг, не ожидал.

    Андрей О_о

    3 Окт 11 at 11:17

  2. Спасибо что восстановил блог

    >С тех пор, я чутка поумнел и для организации потоков наследуюсь от класса Thread.

    это вот так:


    class Register(threading.Thread):
    def __init__(self,config):

    и т.д?

    А чем был плох старый способ из «Пример 3. Очереди.» ?

    ne0zx

    3 Окт 11 at 19:36

  3. Ага, из моего же скрипта код=) Ну так удобней, если очень много входных данных использовать и применять тот старый способ, придется делать кучу параметров у функции, которую будем ветвить. А тут класс, ООП, все дела, да и смотрится красиво и понятно, а в том случае при усложнении примера костыли одни получаются.

    kalombo

    3 Окт 11 at 19:41

  4. привет, подскажи пожалуйста, зачем здесь:
    for i in xrange(processes):
    t = Serfer(queue) # создаем процесс
    t.start() # стартуем
    time.sleep(0.1)

    мы делаем паузу (то есть time.sleep(0.1)). я так понимаю, что должно пройти некоторое время, пока передаваемая очередь пройдёт pickling и станет доступна порождённому процессу в шаред памяти?
    В общем, есть ли какой-то способ не делать паузу явно, а как-то ждать ровно необходимое время (которое может быть и больше 0.1 сек)… то есть ровно столько, сколько потребуется для инициализации нового процесса ?

    Спасибо.

    xxx

    27 Окт 11 at 23:30

  5. Гм, работая с потоками, паузу я делал для того, чтобы выводимый текст в консоли не накладывался друг на друга, если я делаю print text из потока. В этом примере сообщений в командную строку я не вывожу, а задержку просто забыл убрать =) По идее все эти паузы можно закомментировать.

    kalombo

    28 Окт 11 at 10:08

  6. ясно, просто я тут как-то начал замарачиваться с синхронизацей всех пораждённых процессов пауков, и потребовалось передавать в подпроцессы Кондишины и прочие объекты IPC синхронизации, так вот, эти объекты создавались только после истечения некоторой паузы, которую нужно было делать сразу после process.start(), и которая всегда само-собой была разной (что бы этот объект смог стать доступным после pickling-а уже в пространстве процесса), и подумал, что и в случае, когда используем обычные очереди, нужна такая пауза.

    Кстати, всё-таки не пытался ради спортивного интереса заставить это всё работать в потоках, а не процессах? уж слишком межу ними синхронизироваться неудобно

    xxx

    28 Окт 11 at 21:05

  7. Я ж написал, что невозможно заставить spynner работать в потоках, особенности библиотеки Qt, к сожалению. Так что только процессы, вообще splinter посмотреть попробуй, если честно не понравился мне этот spynner

    kalombo

    29 Окт 11 at 02:59

  8. Если выставлять число процессов меньше числа урлов то не работает

    Висит вот с такими ошибками:
    Application asked to unregister timer 0x1f000002 which is not registered in this thread. Fix application.
    QObject::connect: Cannot connect (null)::configurationAdded(QNetworkConfiguration) to QNetworkConfigurationManager::configurationAdded(QNetworkConfiguration)
    QObject::connect: Cannot connect (null)::configurationRemoved(QNetworkConfiguration) to QNetworkConfigurationManager::configurationRemoved(QNetworkConfiguration)
    QObject::connect: Cannot connect (null)::configurationUpdateComplete() to QNetworkConfigurationManager::updateCompleted()
    QObject::connect: Cannot connect (null)::onlineStateChanged(bool) to QNetworkConfigurationManager::onlineStateChanged(bool)
    QObject::connect: Cannot connect (null)::configurationChanged(QNetworkConfiguration) to QNetworkConfigurationManager::configurationChanged(QNetworkConfiguration)
    Application asked to unregister timer 0×3000007 which is not registered in this thread. Fix application.
    QObject::connect: Cannot connect (null)::configurationAdded(QNetworkConfiguration) to QNetworkConfigurationManager::configurationAdded(QNetworkConfiguration)
    QObject::connect: Cannot connect (null)::configurationRemoved(QNetworkConfiguration) to QNetworkConfigurationManager::configurationRemoved(QNetworkConfiguration)
    QObject::connect: Cannot connect (null)::configurationUpdateComplete() to QNetworkConfigurationManager::updateCompleted()
    QObject::connect: Cannot connect (null)::onlineStateChanged(bool) to QNetworkConfigurationManager::onlineStateChanged(bool)
    QObject::connect: Cannot connect (null)::configurationChanged(QNetworkConfiguration) to QNetworkConfigurationManager::configurationChanged(QNetworkConfiguration)

    Arceny

    1 Дек 11 at 00:51

Комментировать

Перед отправкой формы:
Human test by Not Captcha