CURLOPT_POSTFIELDS сломал мой моск!

Тема в разделе "PHP", создана пользователем bugargen, 9 янв 2011.

Модераторы: latteo
  1. bugargen

    bugargen

    Регистр.:
    24 апр 2008
    Сообщения:
    232
    Симпатии:
    19
    Почему этот код не работает:
    PHP:
        curl_setopt $chCURLOPT_POSTFIELDShttp_build_query ( array
            (
                
    '__VIEWSTATE' => '/wEPDwUKMTcyNjAyOTg3Mg9kFgICAQ9kFgRmDw8WAh4EVGV4dAUIRGVjZW1iZXJkZAIEDzwrAAsAZGRNeirC79BNdveVTXLn6ksGFliaAw==',
                
    '__EVENTVALIDATION' => '/wEWBQLE8OOoCgKagaDZAgKuyd61DAK+sdPcCALCi9reAyU2ln31VgW5dbKcpzILrNVZXPDU',
                
    'ddlShowEstimate' => "Don't show estimates",
                
    'txtKeyword' => 'kakoito keyword',
                
    'btnSubmit' => 'Submit'
            
    ) ) );
    Хотя, если полученную через http_build_query строку вставить непосредственно, т.е.:
    PHP:
    curl_setopt $chCURLOPT_POSTFIELDS'__VIEWSTATE=%2FwEPDwUKMTcyNjAyOTg3Mg9kFgICAQ9kFgRmDw8WAh4EVGV4dAUIRGVjZW1iZXJkZAIEDzwrAAsAZGRNeirC79BNdveVTXLn6ksGFliaAw%3D%3D&__EVENTVALIDATION=%2FwEWBQLE8OOoCgKagaDZAgKuyd61DAK%2BsdPcCALCi9reAyU2ln31VgW5dbKcpzILrNVZXPDU&ddlShowEstimate=Don%27t+show+estimates&txtKeyword=kakoito+keyword&btnSubmit=Submit' );
    то всё работает.

    PS: Если из первого примера убрать использование http_build_query, то тоже всё работает, но ОООЧЕНЬ медленно.
     
  2. lungsmoney

    lungsmoney Постоялец

    Регистр.:
    25 апр 2008
    Сообщения:
    81
    Симпатии:
    23
    Если именно в таком порядке строки = то хз.
    Попробуй вынести http_build_query
    PHP:
    curl_setopt $chCURLOPT_POST);
    $FF http_build_query ( array
            (
                
    '__VIEWSTATE' => '/wEPDwUKMTcyNjAyOTg3Mg9kFgICAQ9kFgRmDw8WAh4EVGV4dAUIRGVjZW1iZXJkZAIEDzwrAAsAZGRNeirC79BNdveVTXLn6ksGFliaAw==',
                
    '__EVENTVALIDATION' => '/wEWBQLE8OOoCgKagaDZAgKuyd61DAK+sdPcCALCi9reAyU2ln31VgW5dbKcpzILrNVZXPDU',
                
    'ddlShowEstimate' => "Don't show estimates",
                
    'txtKeyword' => 'kakoito keyword',
                
    'btnSubmit' => 'Submit'
            
    ) );
     
    curl_setopt $chCURLOPT_POSTFIELDS$FF ); 
     
  3. bugargen

    bugargen

    Регистр.:
    24 апр 2008
    Сообщения:
    232
    Симпатии:
    19
    Пробовал - не работает.

    Т.е. смотрите, что получается..
    Если получить результат http_build_query непосредственно в CURLOPT_POSTFIELDS или в переменную, то это не работает. А если этот результат вывести на экран, скопировать эту строку и, опять же, вставить в CURLOPT_POSTFIELDS или в переменную - то всё работает! НУ НЕ БРЕД???
    Ведь одна и таже строка генерируется, хоть в переменную, хоть на экран. Разве не так?
     
  4. trooll

    trooll PHP кодер

    Регистр.:
    22 дек 2008
    Сообщения:
    503
    Симпатии:
    116
    Не советую использовать http_build_query(), ибо были замечены косяки при обработки этой функцией, пришлось отказаться от использования. Точно что за косяк был вспомнить не могу, но что то связанное с символом &, толи не проставился или наоборот был проставлен, в общем если вдруг вспомню отпишусь в теме что да как.

    Сам использую следующую функцию, нареканий пока не было:

    PHP:
        function genQueryGet($d false$s '&') {
            if(
    is_array($d)){
                
    $r '';
                foreach (
    $d as $k => $v) {
                    
    $r $r.$k.'='.$v.$s;
                }
                
    $r substr($r0, -1);
                return 
    $r;
            }else{
                return 
    false;
            }
        }
    Так же проверти кодировку отправляемых данных в этом иногда также кроиться причина не работоспособности и многих косяков.
     
  5. bugargen

    bugargen

    Регистр.:
    24 апр 2008
    Сообщения:
    232
    Симпатии:
    19
    trool
    И функцию я такую создавал и использовал уже, ничерта не работает :) Дело в чём-то другом.
     
  6. steel_HILL

    steel_HILL Постоялец

    Регистр.:
    15 апр 2010
    Сообщения:
    53
    Симпатии:
    14
    Возможно, что косяк с УРЛенкодингом, попробуй заменить -
    PHP:
    '__VIEWSTATE' => '/wEPDwUKMTcyNjAyOTg3Mg9kFgICAQ9kFgRmDw8WAh4EVGV4dAUIRGVjZW1iZXJkZAIEDzwrAAsAZGRNeirC79BNdveVTXLn6ksGFliaAw==',
                
    '__EVENTVALIDATION' => '/wEWBQLE8OOoCgKagaDZAgKuyd61DAK+sdPcCALCi9reAyU2ln31VgW5dbKcpzILrNVZXPDU',
    на -

    PHP:
    '__VIEWSTATE' => '%2FwEPDwUKMTcyNjAyOTg3Mg9kFgICAQ9kFgRmDw8WAh4EVGV4dAUIRGVjZW1iZXJkZAIEDzwrAAsAZGRNeirC79BNdveVTXLn6ksGFliaAw%3D%3D',
                
    '__EVENTVALIDATION' => '%2FwEWBQLE8OOoCgKagaDZAgKuyd61DAK%2BsdPcCALCi9reAyU2ln31VgW5dbKcpzILrNVZXPDU',
    ну и так далее...
     
  7. pitkina

    pitkina

    Регистр.:
    1 апр 2007
    Сообщения:
    253
    Симпатии:
    176
    отдельные символы http_build_query переводит в html формат:

    PHP:
    $post html_entity_decode(http_build_query(array(
                
    '__VIEWSTATE' => '/wEPDwUKMTcyNjAyOTg3Mg9kFgICAQ9kFgRmDw8WAh4EVGV4dAUIRGVjZW1iZXJkZAIEDzwrAAsAZGRNeirC79BNdveVTXLn6ksGFliaAw==',
                
    '__EVENTVALIDATION' => '/wEWBQLE8OOoCgKagaDZAgKuyd61DAK+sdPcCALCi9reAyU2ln31VgW5dbKcpzILrNVZXPDU',
                
    'ddlShowEstimate' => "Don't show estimates",
                
    'txtKeyword' => 'kakoito keyword',
                
    'btnSubmit' => 'Submit'
            
    )));

    curl_setopt($chCURLOPT_POSTFIELDS,$post);
    но оптимальный вариант - прямое указание массива
    PHP:
    curl_setopt ($ch,CURLOPT_POSTFIELDS,$array);
     
  8. bugargen

    bugargen

    Регистр.:
    24 апр 2008
    Сообщения:
    232
    Симпатии:
    19
    steel_HILL
    Так html_build_query итак сам прекрасно декодирует эти значения к такому виду. Это легко проверить, если вывести сформированную строку запроса на экран. Но почему-то эта строка замечательно и правильно выглядит на экране, но в POSTFIELD передаётся неверно. Хотя если её скопировать с экрана, вставить в кавычках (т.е. - как и любую другую строку) в POSTFIELD, то всё замечательно срабатывает.

    Я уж устал это объяснять :)

    ЗЫ: Все данные, кроме кнопки сабмит и ещё одного поля - динамичны, т.е. - изменяются постоянно.

    Добавлено через 16 минут
    pitkina
    Этот вариант работает ровно столько же медленно, сколько и прямое указание массива.

    Я бы и успокоился на прямом указании массива (что с самого начала и сделал:(
    PHP:
    curl_setopt $chCURLOPT_POSTFIELDS, array
            (
                
    '__VIEWSTATE' => '/wEPDwUKMTcyNjAyOTg3Mg9kFgICAQ9kFgRmDw8WAh4EVGV4dAUIRGVjZW1iZXJkZAIEDzwrAAsAZGRNeirC79BNdveVTXLn6ksGFliaAw==',
                
    '__EVENTVALIDATION' => '/wEWBQLE8OOoCgKagaDZAgKuyd61DAK+sdPcCALCi9reAyU2ln31VgW5dbKcpzILrNVZXPDU',
                
    'ddlShowEstimate' => "Don't show estimates",
                
    'txtKeyword' => 'kakoito keyword',
                
    'btnSubmit' => 'Submit'
            
    ) );
    но ведь медленно, сволочь, работает! Это незаметно, когда цикл в один проход, а когда этот запрос выполняется 5, 10, 100 раз - тормоза колоссальные, нежели бы я просто методом GET отправил: http://ляляля.aspx?q=какойнить+кейворд. И ладно бы это было из-за самого, КАК ТАКОВОГО, метода POST, так ведь когда я делаю тоже самое, но сам, через форму сайта в браузере - запрос и ответ выполняются молниеносно. Как так? Браузер же тоже данные кодирует перед отправкой, но тормозов таких нет.
     
  9. steel_HILL

    steel_HILL Постоялец

    Регистр.:
    15 апр 2010
    Сообщения:
    53
    Симпатии:
    14
    Ну как бы, сравнивать скомпилированый браузер с PHP-интерпретатором не совсем корректно...

    Если хочешь, то глянь на Snoopy - http://sourceforge.net/projects/snoopy/
    Хотя сомневаюсь, что он летать будет, ведь при мульти-поточной работе в первую очередь все зависит от твоего провайдера...
     
  10. bugargen

    bugargen

    Регистр.:
    24 апр 2008
    Сообщения:
    232
    Симпатии:
    19
    Да я бы и забил на это дело уже давно и юзал бы на 100% работающий вариант без всяких http_build_query:
    PHP:
        curl_setopt $chCURLOPT_POSTFIELDS, array
            (
                
    '__VIEWSTATE' => '/wEPDwUKMTcyNjAyOTg3Mg9kFgICAQ9kFgRmDw8WAh4EVGV4dAUIRGVjZW1iZXJkZAIEDzwrAAsAZGRNeirC79BNdveVTXLn6ksGFliaAw==',
                
    '__EVENTVALIDATION' => '/wEWBQLE8OOoCgKagaDZAgKuyd61DAK+sdPcCALCi9reAyU2ln31VgW5dbKcpzILrNVZXPDU',
                
    'ddlShowEstimate' => "Don't show estimates",
                
    'txtKeyword' => 'kakoito keyword',
                
    'btnSubmit' => 'Submit'
            
    ) );
    если бы не следующий момент...

    Сравним два варианта, на примере отправки капчи..

    PHP:
        curl_setopt $chCURLOPT_POSTFIELDS, array
            (
                
    'recaptcha_challenge_field' => 'тра-ля-ля',
                
    'recaptcha_response_field' => 'тру-лю-лю',
                
    'submit' => "I'm a human"
            
    ) );
    и

    PHP:
        curl_setopt $chCURLOPT_POSTFIELDShttp_build_query ( array
            (
                
    'recaptcha_challenge_field' => 'тра-ля-ля',
                
    'recaptcha_response_field' => 'тру-лю-лю',
                
    'submit' => "I'm a human"
            
    ) ) );
    Теперь взглянем на starttransfer_time из curl_getinfo:
    - в первом варианте это 2.015;
    - во втором варианте это 0.125.

    Разница очевидна. http_buil_query жжёт по скорости просто нипадецки, т.е. свой хлеб ест не зря. Но, сцуко, в моём случае - он отказывается правильно отрабатывать. Всё дело в этих грёбанных полях грёбанного ASPX (__VIEWSTATE и __EVENTVALIDATION) походу.

    Из всего вышесказанного делаем выводы:
    1. http_build_query очень сильно ускоряет обработку данных в CURLOPT_POSTFIELDS.
    2. Если позволить CURLOPT_POSTFIELDS самому собирать и кодировать массив (т.е. отказаться от http_build_query) - то процесс этот сильно замедляется.
    3. При попытке применения к данным функции urlencode - результат столь же плачевный, что и во втором пункте (это если кто схитрить захочет).