Класс MultiCurl

Статус
В этой теме нельзя размещать новые ответы.

Jeurey

Хранитель порядка
Регистрация
13 Сен 2006
Сообщения
419
Реакции
614
Классы-обертки вокруг curl и curl_multi

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

Посему мною был написал ряд библиотечных классов, которыми я собираюсь поделиться с общественностью фидбэка ради.

Начну с библиотек сетевых подключений, а-ля обертка вокруг функций curl и curl_multi.

В библиотеке представлено два функциональных класса:
  • Pi_Curl
  • Pi_MultiCurl
А так же наследованный от Pi_MultiCurl Pi_MultiCurl_Proxy.

Набор классов можно скачать следующими способами:

Как использовать?
Ниже Вы можете увидеть примеры использования классов:
Pi_MultiCurl
PHP:
<?php

    ini_set('display_errors', true);
    error_reporting(E_ALL);

    include 'libs/curl/pi_curl_exception.php';
    include 'libs/curl/pi_curl.php';

    include 'libs/multicurl/pi_multicurl_exception.php';
    include 'libs/multicurl/pi_multicurl.php';

    $urls    = file('urls.txt');
    $results = array();

    try {
        // Создаем объект MultiCurl
        $cURL   = new Pi_MultiCurl();
    } catch (Pi_MultiCurl_Exception $e) {

        // Обработка исключения
        echo $e->getMessage();
        exit();
    }

    define('URL_STACK_COUNT',   15);
    
    // Количество потоков
    $cURL->setThreadsCount(URL_STACK_COUNT);

    // Таймаут потока
    $cURL->setThreadTimeout(3);

    // Перерыв между потоками в мс
    $cURL->setUsleepTime(300);


    $fwBad  = fopen('bad.txt',  'w+');
    $fwGood = fopen('good.txt', 'w+');
    
    while(sizeof($urls)) {

        $i = URL_STACK_COUNT;   // Будем ложить столько же, сколько и размер стэка
        $_urls = array();       // Очищаем список адресов, которые мы будем ложить в поток

        while($i-- && sizeof($urls)) {
            $_urls[] = trim(array_pop($urls));
        }

        $cURL->setUrls($_urls);
        $results = $cURL->getUrls();

        if($results == Pi_MultiCurl::E_EMPTY_URLS_LIST) {
            continue ;
        }

        foreach ($results as $thread)  {

            // Если скрипт не мог получить страницу
            if(!strlen($thread['contents']) || $thread['errors']) {
                continue ;
            }
            
            if(stripos($thread['contents'], 'some_substring') !== false) {
                fwrite($fwGood, $thread['url'] . "\n");
            } else {
                fwrite($fwBad, $thread['url'] . "\n");
            }
        }
    }

    fclose($fwBad);
    fclose($fwGood);
    unset($cURL);
[/SPOIL]

Pi_Curl
[spoil]
Обработка curl_exec идет напрямую, ввиду заточенности решения под использование классом Pi_MultiCurl. Обещаю поправить :)
PHP:
<?php

    ini_set('display_errors', true);
    error_reporting(E_ALL);

    include 'libs/curl/pi_curl_exception.php';
    include 'libs/curl/pi_curl.php';

    $cURL   = new Pi_Curl;

    $cURL->setDefaultOptions();
    $cURL->setOption('URL',        'http://yandex.ru/');
    $cURL->setOption('TIMEOUT',    10);
    $cURL->applyOptions();

    $result = curl_exec($cURL->getHandle());

Собственно, все. Описать работу Pi_MultiCurl_Proxy обещаю в ближайшее время. Не описан здесь потому, что есть зависимость от стороннего класса Pi_ProxyDispatcher, экземпляр которого является диспетчером прокси-списков.

UPD: данный класс писался для собственного proxy-комбайна. Dev-версия лежит на рапиде и доступна для скачивания. Размера не пугайтесь - в ней зашит проект, дамп базы, визуальный фреймворк и приложения. Если кому нужно - забираем тут:

Спасибо за внимание :)
 

Вложения

  • pi_multicurl_0.1.1.zip
    25,1 KB · Просмотры: 48

Jeurey

Хранитель порядка
Регистрация
13 Сен 2006
Сообщения
419
Реакции
614
UPD: версия 0.1.2 от 2009.05.12
 

Вложения

  • pi_multicurl_0.1.2.zip
    25 KB · Просмотры: 33

KillDead

Хранитель порядка
Регистрация
11 Авг 2006
Сообщения
894
Реакции
579
В классе есть возможность каждому потоку передать свои опции?
 

fuck0ff

Постоялец
Регистрация
2 Сен 2007
Сообщения
92
Реакции
50
KillDead, да, есть метод setOption, неплохо написан, автору респект
 

KillDead

Хранитель порядка
Регистрация
11 Авг 2006
Сообщения
894
Реакции
579
KillDead, да, есть метод setOption, неплохо написан, автору респект
Мне нужно было каждому потоку отправить свой пост-запрос. А setOption определяет одни опции для всех.
В общем добавил:

PHP:
        /** 
         * Для каждого потока передаём свои опции
         * @param array $array
         */        
        public function setCurlOptionArr($array) {
            $this->_additionalOptionsArr = $array;
        }
......
Чуть изменил:
PHP:
        /**
         * Установка настроек Curl-объекта по-умолчанию
         * @param string $threadId
         */
        protected function _setThreadOptions($threadId) {
            $Curl   = $this->_curlObjects[$threadId];
 
            $Curl->setDefaultOptions();
            $Curl->setOption('URL',        array_pop(&$this->_urls));
            $Curl->setOption('TIMEOUT',    $this->_threadTimeout);
 
   ############ 
    if($this->_additionalOptionsArr) 
    $this->_additionalOptions =  array_pop($this->_additionalOptionsArr);
   ############     
 
            foreach ($this->_additionalOptions as $name => $value) {
                $Curl->setOption($name, $value);
            }
            $Curl->applyOptions();
        }
Чтобы на выходе getUrls() был не хаотичный массив, перемешал его
PHP:
        public function getUrls() {
...........
 
                    krsort ($results);
 
 
                    $this->_killThread($threadId);
                    $this->_threadsRunning--;
Передача самого массива классу

PHP:
   while ( $i -- && sizeof ( $urls['url'] ) ) {
    $_urls [] =  array_shift ($urls['url'] ) ;
    $_opt [] =  array_shift ($urls['options'] ) ;
 
   }
   $cURL->setUrls ( $_urls );
   $cURL->setCurlOptionArr($_opt);
 

Jeurey

Хранитель порядка
Регистрация
13 Сен 2006
Сообщения
419
Реакции
614
Обновление библиотеки до версии 0.1.3 от 2009.06.06
Что изменено?
- Добавлен класс Pi_ProxyDispatcher для работы Pi_MultiCurl со списком прокси-серверов
- Примеры вынесены в отдельную папку
- Произведен рефакторинг кода


По поводу установки отдельных свойств для каждого потока - посмотрите в сторону уже существующего "живого" примера - класса Pi_MultiCurl_Proxy (он входил в пакет pi_multicurl с самой первой версии:( там идет переопределение метода Pi_MultiCurl_Proxy::_setThreadOptions , что позволяет изменять свойства потока ВНЕ основной библиотеки.

KillDead, можно сделать так, как ты сделал, но что будешь делать теперь, когда библиотека была изменена? Снова править обновленный код? Воспользуйся ООП, если внесение изменений в код действительно необходимо ;)
 

Вложения

  • pi_multicurl_0.1.3.zip
    9,8 KB · Просмотры: 76

KillDead

Хранитель порядка
Регистрация
11 Авг 2006
Сообщения
894
Реакции
579
Просто я подумал- данная функция понадобится в 60 случаях из 100. И возможно можно было её включить в класс, а не вне. :nezn:
----------
А так классный класс. :ay:
 

KillDead

Хранитель порядка
Регистрация
11 Авг 2006
Сообщения
894
Реакции
579
:ah: Хотелось бы увидеть какой-нить browser-класс построенный на данном классе: Т.е. просто задал настройки, дал массив с урлами и на выходе получил массив с результатоми.
У мну есть что-то подобное, но построенное на таком говнокоде...
 

KillDead

Хранитель порядка
Регистрация
11 Авг 2006
Сообщения
894
Реакции
579
UPD: версия 0.1.2 от 2009.05.12
Была ли попытка связать эту библиотеку с работой с ftp? Я Попытался, но переодически библиотека убивает апач- один и тотже скрипт то вылетает, то выполняется без помех. Сам апач говорит
log: Parent: child process exited with status 0 -- Restarting.
При использовании мультикурла для тех же параметров ничего подобного не наблюдалось. :nezn:
Есть мысли как побороть?
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху