PHP curl multi на защищенном сайте - PullRequest
2 голосов
/ 25 января 2012

Я сейчас использую следующий (старый) код для входа на сайт ...

public function login() {
    $url1 = 'https://...';  /* Initial page load to collect initial session cookie data */
    $url2 = 'https://...';  /* The page to POST login data to */
    $url3 = 'https://...';  /* The page redirected to to test for success */
    $un = 'user';
    $pw = 'pass';

    $post_data = array(
        'authmethod' => 'on',
        'username'   => $un,
        'password'   => $pw,
        'hrpwd'      => $pw
    );

    $curlOpt1 = array(
        CURLOPT_URL            => $url1,
        CURLOPT_COOKIEJAR      => self::COOKIEFILE,
        CURLOPT_COOKIEFILE     => self::COOKIEFILE,
        CURLOPT_FOLLOWLOCATION => TRUE,
        CURLOPT_HEADER         => FALSE,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_SSL_VERIFYPEER => FALSE
    );

    $curlOpt2 = array(
        CURLOPT_URL            => $url2,
        CURLOPT_COOKIEJAR      => self::COOKIEFILE,
        CURLOPT_COOKIEFILE     => self::COOKIEFILE,
        CURLOPT_FOLLOWLOCATION => TRUE,
        CURLOPT_POST           => TRUE,
        CURLOPT_POSTFIELDS     => http_build_query($post_data)
    );

    $this->ch = curl_init();
    if ( !$this->ch ) {
        throw new Exception('Unable to init curl. ' . curl_error($curl));
    }

    /* Load the login page once to get the session ID cookies */
    curl_setopt_array( $this->ch, $curlOpt1 );
    if ( !curl_exec( $this->ch ) ) {            
        throw new Exception( 'Unable to retrieve initial auth cookie.' );
    }

    /* POST the login data to the login page */
    curl_setopt_array($this->ch, $curlOpt2);
    if ( !curl_exec( $this->ch ) ) {
        throw new Exception( 'Unable to post login data.' );
    }

    /* Verify the login by checking the redirected url. */
    $header  = curl_getinfo( $this->ch );
    $retUrl = $header['url'];

    if ( $retUrl == $url3 ) {
        /* Reload the login page to get the auth cookies */
        curl_setopt_array( $this->ch, $curlOpt1 );
        if ( curl_exec( $this->ch ) ) {
            return true;
        } else {
            throw new Exception( 'Unable to retrieve final auth cookie.' );
        }
    } else {
        throw new Exception( 'Login validation failure.' );
    }

    return false;
}

Затем я использую ...

public function getHtml($url) {
    $html = FALSE;

    try {
        curl_setopt($this->ch, CURLOPT_URL, $url);
        $page = curl_exec($this->ch);
    } catch (Exception $e) {
        ...
    }

    /* Remove all tabs and newlines from the HTML */
    $rmv = array("\n","\t");
    $html = str_replace($rmv, '', $page);

    return $html;
}

... длякаждая страница запроса.Мой вопрос, как я могу преобразовать это, чтобы использовать curl_multi_exec, чтобы сделать несколько сотен просмотров быстрее?Я не могу найти примеры curl_multi с логином.Я просто заменяю все curl_execs на curl_multi_exec?Кроме того, если вы видите какие-либо явные ошибки, комментарии, безусловно, приветствуются.

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

1 Ответ

1 голос
/ 16 мая 2012

Это было какое-то время, но я хотел опубликовать свое окончательное решение. Я нашел потрясающую библиотеку для нескольких скручиваний, roll-curl , которая помогла. По сути, после сбора файла cookie для входа в систему (показанного в моем исходном вопросе) я передаю его и другие параметры обратно в экземпляр свертываемого curl для каждого мультизапроса, а затем выполняю пакет. Работает как шарм.

public function getMultiPage(array $urls, $url_prepend=NULL, $callback) {
    $rc = new RollingCurl(array('Att_Screen_Scraper', $callback));
    $rc->window_size = 15;   /* number of threads to run */
    $rc->options = array(
        CURLOPT_COOKIEJAR      => self::COOKIEFILE,
        CURLOPT_COOKIEFILE     => self::COOKIEFILE,
        CURLOPT_FOLLOWLOCATION => TRUE,
        CURLOPT_HEADER         => FALSE,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_SSL_VERIFYPEER => FALSE
    );

    foreach ($urls as $i=>$url) {
        $request = new RollingCurlRequest($url_prepend . $url);
        echo $url_prepend . $url . "<br>\n";
        $rc->add($request);
    }

    if(!$rc->execute()) {
        throw new Exception('RollingCurl execute failed');
    }

    return TRUE;
}

Обратите внимание, что для этого решения требуется обратный вызов для обработки возврата каждого запроса. Документация RollingCurl хорошо описывает это, поэтому я не буду повторять это здесь.

...