Как отправить куки с помощью PHP cURL в дополнение к CURLOPT_COOKIEFILE?
Описание проблемы:
Я занимаюсь парсингом контента с веб-сайта после отправки формы, однако мой скрипт иногда не работает, например, в 2 из 5 случаев он терпит неудачу. Я использую PHP cURL, а также COOKIEFILE и COOKIEJAR для обработки куки. При сравнении заголовков, отправляемых моим браузером (когда я посещаю целевой сайт и использую live http headers), и заголовков, отправляемых через PHP, я заметил множество различий.
Мой браузер отправляет гораздо больше переменных куки, чем PHP cURL. Я предполагаю, что это связано с тем, что большинство куки устанавливаются с помощью JavaScript, но я не уверен в этом.
Я использую следующий код для парсинга и показываю заголовки, отправляемые моим браузером и PHP cURL:
$ckfile = tempnam ("/tmp", 'cookiename');
$url = 'https://www.domain.com/firststep';
$poststring = 'variable1=4&variable2=5';
$ch = curl_init ($url);
curl_setopt ($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $poststring);
$output = curl_exec ($ch);
curl_close($ch);
$url = 'https://www.domain.com/nextstep';
$poststring = 'variableB1=4&variableB2=5';
$ch = curl_init ($url);
curl_setopt ($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $poststring);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
$output = curl_exec ($ch);
$headers = curl_getinfo($ch, CURLINFO_HEADER_OUT);
curl_close($ch);
print_r($headers);
При этом вывод заголовков выглядит так:
POST /path HTTP/1.1
User-Agent: Mozilla
Host: domain.subdomain.nl
Accept: */*
Cookie: JSESSIONID=7BC2A5277A4EB07D9A7237A707BE1366; www-20480=MIFBNLFDFAAA
Content-Length: 187
Content-Type: application/x-www-form-urlencoded
А заголовки, полученные с помощью live http headers, выглядят намного более полными.
Вопросы:
Делаю ли я что-то неправильно с обработкой куки в текущем коде, за исключением того, что PHP cURL отправляет очень мало переменных куки по сравнению с браузером? Могут ли другие различия между заголовками, отправляемыми браузером и PHP cURL, повлиять на получение правильного контента?
Не отправляются ли некоторые переменные куки из-за того, что они устанавливаются JavaScript-ом?
Как лучше всего обрабатывать куки, чтобы гарантировать, что все необходимые куки отправляются на удаленный сервер?
Буду признателен за любую помощь!
3 ответ(ов)
Если куки создаются через скрипт, вы можете отправить куки вручную вместе с куками из файла (используя опцию cookie-file
). Например:
# отправка вручную установленного кука
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Cookie: test=cookie"));
# отправка куков из файла
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
В этом случае cURL отправит ваш определенный куки вместе с куками из файла.
Если куки генерируются через JavaScript, вам нужно выяснить, как они создаются, а затем вы сможете отправить их с помощью вышеописанного метода (через HTTP-заголовок).
Куки utma
, utmc
, utmz
наблюдаются, когда куки отправляются из Mozilla. Не стоит беспокоиться об этом.
В конце концов, то, что вы делаете, совершенно правильно. Просто убедитесь, что вы используете абсолютный путь к файлам (например, /var/dir/cookie.txt
), а не относительный.
Всегда включайте режим подробного вывода при работе с cURL. Это очень поможет в отслеживании запросов и сэкономит вам много времени.
curl_setopt($ch, CURLOPT_VERBOSE, true);
Вы можете найти список примеров отправки cookies по следующей ссылке: php-curl-cookbook.
Вот пример кода, который демонстрирует, как использовать cURL для отправки cookies:
$curlHandler = curl_init();
curl_setopt_array($curlHandler, [
CURLOPT_URL => 'https://httpbin.org/cookies',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIEFILE => $cookieFile, // файл с cookies
CURLOPT_COOKIE => 'foo=bar;baz=foo', // отправляемые cookies
/**
* Либо можно установить заголовок
* CURLOPT_HTTPHEADER => [
* 'Cookie: foo=bar;baz=foo',
* ]
*/
]);
$response = curl_exec($curlHandler);
curl_close($curlHandler);
echo $response;
В этом примере мы инициируем cURL, устанавливаем необходимые параметры, включая URL, флаг возврата результата и cookies, которые хотим отправить. Также есть возможность передать cookies через заголовок Cookie
. После выполнения запроса мы закрываем обработчик cURL и выводим ответ.
Ваш код выполняет POST-запрос к API с использованием cURL и управляет файлами cookie. Вот шаги, которые вы выполняете:
Создание файла cookie: Проверяете, существует ли файл
cookies.txt
. Если нет, создаёте его:$cookieFile = "cookies.txt"; if(!file_exists($cookieFile)) { $fh = fopen($cookieFile, "w"); fwrite($fh, ""); fclose($fh); }
Инициализация cURL: Создаёте сессию cURL и задаёте необходимые параметры:
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $apiCall); curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncoded); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); // Использование файла cookie curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile); // Сохранение ответов в файл cookie curl_setopt($ch, CURLOPT_VERBOSE, true);
Выполнение запроса: Выполняете запрос и обрабатываете возможные ошибки:
if(!curl_exec($ch)){ die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch)); } else{ $response = curl_exec($ch); }
Закрытие cURL: Закрываете соединение cURL после выполнения запроса:
curl_close($ch);
Обработка и вывод результата: Декодируете JSON-ответ и выводите его на экран:
$result = json_decode($response, true); echo '<pre>'; var_dump($result); echo'</pre>';
Обратите внимание на то, что вы дважды вызываете curl_exec($ch)
, что может быть ошибкой. Вам следует сохранить результат одного вызова и затем обрабатывать его. Вот исправленный вариант:
$response = curl_exec($ch);
if($response === false) {
die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
}
Эти изменения помогут избежать ненужного выполнения запроса дважды и streamline вашу функцию.
Как получить миниатюру видео с YouTube с помощью YouTube API?
Пример использования PHP и cURL для HTTP POST запроса?
Отправка многомерного массива с помощью PHP и CURL
Что такое заголовок postman-token в сгенерированном коде Postman?
Функции startsWith() и endsWith() в PHP