ФорумПрограммированиеPHP для идиотов → Curl - многопоточность+прокси

Curl - многопоточность+прокси

  • bloxa

    Сообщения: 6 Репутация: N Группа: Кто попало

    Spritz 25 сентября 2009 г. 12:22

    Пытаюсь освоить курл, и встала такая непонятка - многопоточность достигается за счет добавления готовых заданий в список заданий. К каждому заданию я формирую настройки, в т.ч. указываю прокси. Потом весь список выполняется в указанное количество потоков. Но что, если прокси из какого-то задания уже нерабочий - как сделать так, чтобы в случае неработоспособности прокси во время выполнения задачи, прокси менялось на другую? Не могу понять, как такое сделать в многопоточности.
    Условно должно быть так:
    1) Сделал задания, добавил прокси всем
    2) Выполняем задания
    3) Если выполнить не удалось, или результат не удовлетворил условию, то изменить прокси на текущем задании и сделать его еще раз.
  • NRG

    Сообщения: 4761 Репутация: N Группа: в ухо

    Spritz 25 сентября 2009 г. 12:32, спустя 9 минут 48 секунд

    по поводу курла к phpdude,
    по поводу многопоточности к киберспорту =)))))
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 25 сентября 2009 г. 12:49, спустя 16 минут 35 секунд

    bloxa, никак, только проверять потом, получил ли ты ответ и тп
    Сапожник без сапог
  • bloxa

    Сообщения: 6 Репутация: N Группа: Кто попало

    Spritz 27 сентября 2009 г. 11:12, спустя 1 день 22 часа 23 минуты

    А можно тогда при выполнении мультикурла хоть как-то контролировать ответ одного потока?
    Примерно так:
    1) Добавили задания
    2) Запустили мультикурл
    3) Далее к каждомо потоку применяется условие:
    если страница, которую отдал поток нам не подходит, то sleep, затем заново запускаем поток.

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

    На данный момент имеется такой код:
    $connomains - массив с нужными урлами.


    $mh = curl_multi_init();

    foreach ($connomains as $i => $url) {
          $conn[$i] = curl_init($url);
      curl_setopt($conn[$i], CURLOPT_URL, $url);
    curl_setopt($conn[$i], CURLOPT_FAILONERROR, 1);
    curl_setopt($conn[$i], CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER, 1);
    //curl_setopt($conn[$i], CURLOPT_TIMEOUT, 15);
    curl_setopt($conn[$i], CURLOPT_GET, 1);
    curl_setopt($conn[$i], CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)');
      curl_multi_add_handle ($mh,$conn[$i]);
    }

    // start performing the request
    do {
     $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);

    while ($active and $mrc == CURLM_OK) {
     // wait for network
     if (curl_multi_select($mh) != -1) {
       // pull in any new data, or at least handle timeouts
       do {
         $mrc = curl_multi_exec($mh, $active);
       } while ($mrc == CURLM_CALL_MULTI_PERFORM);
     }
    }

    if ($mrc != CURLM_OK) {
     print "Curl multi read error $mrc\n";
    }

    // retrieve data
    foreach ($connomains as $i => $url) {
     if (($err = curl_error($conn[$i])) == '') {
       $res[$i]=curl_multi_getcontent($conn[$i]);
     } else {
       print "Curl error on handle $i: $err\n";
     }
     curl_multi_remove_handle($mh,$conn[$i]);
     curl_close($conn[$i]);
    }
    curl_multi_close($mh);
  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 24 марта 2011 г. 7:15, спустя 542 дня 21 час 3 минуты

    А можно тогда при выполнении мультикурла хоть как-то контролировать ответ одного потока?
    Примерно так:
    1) Добавили задания
    2) Запустили мультикурл
    3) Далее к каждомо потоку применяется условие:
    если страница, которую отдал поток нам не подходит, то sleep, затем заново запускаем поток.

    присоединяюсь к вопросу, хотя предвижу что хуй, придётся запускать отдельный процесс. но гуру могут высказацца
    не всё полезно, что в swap полезло
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 24 марта 2011 г. 8:08, спустя 52 минуты 31 секунду

    хз есть ли в паблике подобные классы, у меня есть :-)

    Но я никому его не дам, обещал себе типа)
    Сапожник без сапог
  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 24 марта 2011 г. 10:30, спустя 2 часа 22 минуты 9 секунд

    phpdude, давать не надо, просто скажи как сделал - через curl или через pcntl
    не всё полезно, что в swap полезло
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 24 марта 2011 г. 10:36, спустя 6 минут 40 секунд

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

    да и переделать несложно
    Сапожник без сапог
  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 24 марта 2011 г. 10:56, спустя 19 минут 44 секунды

    через курл конечно, мультикурл

    это получается синхронный мультизапрос )
    что если 9 из десяти выполняются за 0.3 секунды, а один выполняется 5 секунд? )
    не всё полезно, что в swap полезло
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 24 марта 2011 г. 10:59, спустя 2 минуты 40 секунд

    что если 9 из десяти выполняются за 0.3 секунды, а один выполняется 5 секунд? )

    все остальные обработаются за 0.3. у меня с пуллингом, указываешь горлышко выполняющихся запросов в 100 например, пусть даже один зависнет, 99 выполнятся как только данные от них придут. я парсил rutracker ))

    в 300 потоков по моему через 5 тыс прокси. сокрость была удобная :-)
    Сапожник без сапог
  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 24 марта 2011 г. 11:10, спустя 11 минут 18 секунд

    с пуллингом

    эт как?
    Спустя 30 сек.
    99 выполнятся как только данные от них придут

    это за счёт чего имею ввиду
    не всё полезно, что в swap полезло
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 24 марта 2011 г. 11:21, спустя 11 минут 6 секунд

    это за счёт чего имею ввиду

    curl multi выполняется асинхронно … пока эти 5 секундный запрос выполняет, я успевая обработать все 99 ответов.

    эт как?

    ну … с набором дескрипторов другими словами %) :D
    Сапожник без сапог
  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 24 марта 2011 г. 12:09, спустя 48 минут 12 секунд

    phpdude, моя всё равно не догонять. вот мой код:


    class Mycurl {

    function __construct(){
    $this->default_opts = array(
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
    CURLOPT_CONNECTTIMEOUT => 0,
    CURLOPT_TIMEOUT => 60,
    CURLOPT_ENCODING => 'gzip,deflate',
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_HEADER => false,
    CURLOPT_AUTOREFERER => true,
    CURLOPT_FAILONERROR => true,
    );
    }

    public function httpGetMulti($urls, array $curl_opts = array(), array $headers = array()){
    $this->last_multi_info = array();
    $this->last_multi_headers = array();
    $this->curl_map = array();
    $result = array();
    $ch = array();
    $this->last_multi_error = array();
    $mandatory_opts = array(
    CURLOPT_HTTPGET => true,
    CURLOPT_HEADERFUNCTION => array(&$this, 'saveHeadersMultiCallback'),
    );
    $curl_opts = array_replace($this->default_opts, $curl_opts, $mandatory_opts);
    if (!empty($headers)){
    $mandatory_opts = array(CURLOPT_HTTPHEADER => $headers);
    $curl_opts = array_replace($curl_opts, $mandatory_opts);
    }
    $mh = curl_multi_init();
    foreach ($urls as $k=>$url){
    $this->last_multi_headers[$k] = array();
    $ch[$k] = curl_init($url);
    $this->curl_map[$k] = $ch[$k];
    curl_setopt_array($ch[$k], $curl_opts);
    curl_multi_add_handle($mh, $ch[$k]);
    }
    $active = null;
    // start performing the request
    do {
    $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);

    while ($active && $mrc == CURLM_OK) {
    // wait for network
    if (curl_multi_select($mh) != -1) {
    // pull in any new data, or at least handle timeouts
    do {
    $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    }
    }

    if ($mrc != CURLM_OK) {
    $this->last_error = "Curl multi read error $mrc";
    }

    foreach ($urls as $k=>$url){
    if (($err = curl_error($ch[$k])) == '') {
    $result[$k] = curl_multi_getcontent($ch[$k]);
    $this->last_multi_error[$k] = null;
    } else {
    $result[$k] = null;
    $this->last_multi_error[$k] = "Curl error on handle $k: $err";
    }
    $this->last_multi_info[$k] = curl_getinfo($ch[$k]);
    curl_multi_remove_handle($mh, $ch[$k]);
    curl_close($ch[$k]);
    }
    return $result;
    }

    /**
    * Callback for CURLOPT_HEADERFUNCTION for multimode requests
    * @param resource $ch
    * @param string $header
    * @return int
    */
    protected function saveHeadersMultiCallback($ch, $header){
    if (trim($header) != ''){
    $k = array_search($ch, $this->curl_map);
    if ($k !== false){
    $this->last_multi_headers[$k][] = trim($header);
    }
    }
    return strlen($header);
    }

    }


    запросы тут выполняются вот в этом блоке:


    // start performing the request
    do {
       $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);

    while ($active && $mrc == CURLM_OK) {
     // wait for network
       if (curl_multi_select($mh) != -1) {
        // pull in any new data, or at least handle timeouts
           do {
               $mrc = curl_multi_exec($mh, $active);
           } while ($mrc == CURLM_CALL_MULTI_PERFORM);
       }
    }


    В какой момент можно перехватить завершение отдельного curl-потока?
    не всё полезно, что в swap полезло
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 24 марта 2011 г. 14:07, спустя 1 час 57 минут 30 секунд

    на память не скажу))) не помню честно :D

    смотреть надо
    Сапожник без сапог
  • fgets

    Сообщения: 1099 Репутация: N Группа: Кто попало

    Spritz 24 марта 2011 г. 15:47, спустя 1 час 39 минут 40 секунд

    вот мой велосипед http://sourceforge.net/projects/extracurl/
    на нем многопоточность реализована так:
    $curl->upoint('http://example.com');
    $curl->upoint('http://example.net');
    $curl->upoint('http://example.org');
    print_r($curl());

    мультикурл это лишь псевдомногозадачность, но многозадачность всё же в php есть - копать в строну stream_select
    Спустя 73 сек.
    ой бля перпутал слова многозадачность и многопоточность
    Спустя 36 сек.
    а ваще конечно мощно реализовывать потоки через fork

Пожалуйста, авторизуйтесь, чтобы написать комментарий!