Класс MultiCurl

Тема в разделе ".:: Готовые решения", создана пользователем Jeurey, 2 май 2009.

Статус темы:
Закрыта.
  1. Jeurey

    Jeurey

    Регистр.:
    13 сен 2006
    Сообщения:
    419
    Симпатии:
    576
    Классы-обертки вокруг 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);


    Pi_Curl
    Обработка 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-версия лежит на рапиде и доступна для скачивания. Размера не пугайтесь - в ней зашит проект, дамп базы, визуальный фреймворк и приложения. Если кому нужно - забираем тут: http://rapidshare.com/files/232227570/proxytools.zip

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

    Вложения:

    sasha_ua, Alternator, harpeos и 7 другим нравится это.
  2. Jeurey

    Jeurey

    Регистр.:
    13 сен 2006
    Сообщения:
    419
    Симпатии:
    576
    UPD: версия 0.1.2 от 2009.05.12
     

    Вложения:

  3. KillDead

    KillDead

    Регистр.:
    11 авг 2006
    Сообщения:
    890
    Симпатии:
    561
    В классе есть возможность каждому потоку передать свои опции?
     
  4. fuck0ff

    fuck0ff Постоялец

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

    KillDead

    Регистр.:
    11 авг 2006
    Сообщения:
    890
    Симпатии:
    561
    Мне нужно было каждому потоку отправить свой пост-запрос. А 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);
     
     
  6. Jeurey

    Jeurey

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


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

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

    Вложения:

    KillDead нравится это.
  7. KillDead

    KillDead

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

    KillDead

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

    garden кидала и мошенник

    Заблокирован
    Регистр.:
    13 дек 2006
    Сообщения:
    183
    Симпатии:
    32
    А почему именно говнокод,вообще те не понял?:confused:
     
  10. KillDead

    KillDead

    Регистр.:
    11 авг 2006
    Сообщения:
    890
    Симпатии:
    561
    Была ли попытка связать эту библиотеку с работой с ftp? Я Попытался, но переодически библиотека убивает апач- один и тотже скрипт то вылетает, то выполняется без помех. Сам апач говорит
    При использовании мультикурла для тех же параметров ничего подобного не наблюдалось. :nezn:
    Есть мысли как побороть?
     
Статус темы:
Закрыта.