php curl cookie jar
Как использовать cURL для отправки кукиз
Отправить cookie в cURL можно опцией —cookie:
У опции —cookie есть короткий вариант -b. С этими опциями можно указать как файл, содержащий кукиз, так и строку с паролй ИМЯ=ЗНАЧЕНИЕ. Если аргументом является строка с символом ‘=‘, то он передаётся как есть. В противном случае строка трактуется как имя файла из которого нужно прочитать кукиз.
Сразу несколько кукиз можно передать разделив их точкой с запятой, например:
Если вы хотите сохранить кукиз, то для этого используется опция -c (длинное написание —cookie-jar). Следующий пример запишет полученные от хоста кукиз в файл cookiefile:
А следующий пример прочитает кукиз из файла cookiefile и отправит их хосту:
Смотрите также примеры в статье «Парсинг сайтов: азы, продвинутые техники, сложные случаи» раздел «cURL и аутентификация в веб-формах (передача данных методом GET и POST)».
Допустимо использовать опции для записи и чтения кукиз одновременно в один и тот же файл, как это делают веб-браузеры:
Если нужно написать файл кукиз вручную, то помните, что в документации curl сказано, что используется старый формат файлов кукиз Netscape, который отличается от формата, используемого веб-браузерами. Если вам нужно создать файл кукиз для curl вручную, то это сообщение должно помочь вам.
Файл должен быть записан примерно так:
то есть содержать 7 разделённых табом поолей: домен, tailmatch, путь, безопасность, истекают, имя, значение.
cURL в PHP: примеры POST, GET запросов с headers, cookie, JSON и многопоточностью
В этой статье мы рассмотрим эффективные приемы работы с cURL, отправление POST, GET и т.д. запросов, работу с cookie, заголовки, JSON а также в конце статьи будут некоторые полезные инструменты, которые могут значительно облегчить вам работу с HTTP запросами.
GET запрос при помощи cURL
Для того, чтобы отправить запрос, нужно создать объект при помощи функции curl_init(), а затем следует настроить его.
Все настройки, которые вы можете найти по этой ссылке. Там вы найдете опции, которые мы будем устанавливать функцией curl_setopt, в дальнейших примерах.
Пример простого GET запроса при помощи cURL:
Если в результате сервер вернет нам редирект, то мы по нему автоматически не перейдем. А иногда это бывает полезно. Чтобы cURL автоматически шел по редиректу нужно установить опцию CURLOPT_FOLLOWLOCATION.
С установленной опцией скрипт автоматически перейдет по вернувшемуся редиректу и вернет ответ уже с итоговой страницы.
POST запрос при помощи cURL
Теперь давайте отправим post запрос на адрес https://httpbin.org/anything
Отлично, с GET и POST запросами в cURL мы немного освоились. Теперь разберемся с заголовками, которые мы можем отсылать в запросе.
Заголовки устанавливаются при помощи опции CURLOPT_HTTPHEADER Чтобы получше узнать, для чего нужна эта опция давайте попробуем отправить POST запрос в формате JSON
cURL: POST запрос в формате JSON
Отличия конфигурации JSON запроса от обычного POST запроса заключается в том, что мы кодируем поля при помощи json_encode() И добавляем заголовок Content-Type: application/json
cURL: GET запрос в формате JSON
GET запрос в формате JSON отправляется так же как и POST запрос, просто нужно CURLOPT_CUSTOMREQUEST установить в ‘GET’
cURL и другие виды HTTP запросов: PUT, DELETE, HEAD, PATCH, OPTIONS, CONNECT и т.д.
Стоп, Дмитрий, прекрати выдумывать виды запросов!
Ничего я не выдумываю: HTTP протокол предполагает множество типов HTTP запросов просто POST и GET являются более распространенными.
Чтобы отправить PUT запрос, нужно установить опцию CURLOPT_PUT таким образом:
Это делается по тому же принципу, как и CURLOPT_POST. Но что делать с остальным зоопарком запросов? Разве у cURL есть CURLOPT_DELETE или CURLOPT_HEAD? Нет.
Для того, чтобы отправлять другие виды запросов есть другая опция: CURLOPT_CUSTOMREQUEST
Вместо строки curl_setopt($curl, CURLOPT_POST, true); мы явно задаем имя запроса опцией CURLOPT_CUSTOMREQUEST:
Замечание: Не используйте эту возможность пока не убедитесь, что сервер поддерживает данный тип запроса.
Как получить заголовки ответа
В предыдущем примере мы научились посылать заголовки. Самый правильный способ принять заголовки:
Иногда можно встретить другой вариант получения заголовков ответа. К сожалению, они не совсем правильные и могут работать некорректно в некоторых случаях.
Рассмотрим такой пример:
Мы сначала определяем размер заголовка, с помощью CURLINFO_HEADER_SIZE затем вырезаем его из ответа. К сожалению, это может не срабатывать, когда используется прокси или в некоторых случаях редиректа.
Скачивание больших файлов с помощью cURL
Для того, чтобы скачать большой файл пригодится этот способ:
Обратите внимание, если вы будете использовать file_get_contents для скачивания файлов, то файл сначала загружается в оперативную память, а потом сохраняется на диск. Поэтому если файл действительно большой, то скорее всего вашему серверу не хватит памяти. Также к памяти будет требователен следующий код:
Здесь мы скачиваем файл при помощи cURL в оперативную память, а затем сохраняем его на диск. Не смотря на то, что этот способ не годится для скачивания больших файлов, с помощью него можно вполне сохранить простую веб страницу.
Параллельные cURL запросы в PHP
Для чего могут потребоваться многопоточные запросы? Например у нас есть много URL адресов:
И если мы будем по очереди отправлять запросы, то второй запрос начнется только после того, как закончился первый и так далее, а это существенно увеличивает время работы скрипта.
Как выполнить 3 запроса одновременно? В этом нам поможет curl_multi_
Давайте решим конкретную задачу при помощи параллельных curl запросов. Нам нужно отправить одновременно 3 запроса.
Такие параллельные запросы выполняются значительно быстрее чем поочередные.
cURL запросы с сохранением и загрузкой cookie из файла
cURL позволяет нам установить cookie при передачи запросов, а также автоматически принимать и устанавливать cookie, которые нам возвращает сервер, сохраняя их между запросами.
Давайте рассмотрим такой пример:
Теперь cookie у нас хранятся в файле cookie.txt в директории со скриптом (если вы ничего не меняли). Если мы совершаем повторные запросы, то cURL автоматически берет и отправляет cookie на сервер, как и обычный браузер. Таким образом мы можем авторизироваться на сайте и сохранить сеанс между запросами.
Передача cookie без файлов
Иммитация браузера с помощью cURL
Иногда сайт, к которому мы обращаемся может фильтровать запросы, защищаясь от парсинга. Если для этого используются упрощенные способы защиты, например проверка User-Agent, то мы можем легко притвориться, что являемся реальным польователем, который взаимодействует с сайтом через браузер, мы можем послать заголовки и cookie, которые обычно посылает браузер.
В данном примере установлены заголовки, которые посылает Chrome.
В простых ситуациях этого хватает. Но если используется защита при помощи javascript или что-то более продвинутое, то здесь cURL бессилен, и следует использовать либо BAS либо Zennoposter. Либо если вы хотите попытать счастье с PHP, то Selenium.
Не используйте эти знания в противоправных целях.
cURL запросы через прокси
Простой пример для отправки запросов через proxy. Если ваш прокси предполагает авторизацию, то раскомментируйте соответствующие строчки.
Отправка файлов
Авторизация с помощью cURL
HTTP Авторизация
Чтобы с помощью cURL авторизироваться на сайте, который использует Basic HTTP-аутентификацию нужно установить опцию CURLOPT_USERPWD, в которой будет наш логин и пароль.
OAuth авторизация
Авторизация через форму
Давайте применим полученные нами знания и авторизируемся на каком-нибудь сайте. Для этого нужно посмотреть куда форма отправляет данные и отправить туда то же самое.
Допустим на сайте есть такая форма:
Тогда наш cURL запрос должен быть сформирован так:
Автоматическое построение запросов
Перевод консольной команды curl в PHP
И вот еще один сервис, который переводит консольную команду curl в PHP: https://incarnate.github.io/curl-to-php/
Так вы можете создать простые запросы на cURL в PHP не создавая их вручную.
Лайфхак
В консоли браузера, во вкладке сеть, вы можете кликнуть правой кнопкой мыши и скопировать любой запрос в виде команды cURL, а потом с помощью сервиса curl-to-php перевести запрос в PHP. Теперь вы вообще можете сконвертировать в cURL абсолютно любой запрос, который посылает ваш браузер.
Как работать с cURL гораздо проще
Вы можете спросить: почему у cURL такие кривые и страшные методы? У вас может возникнуть желание взять и создать обертку для работы с cURL, чтобы вы могли не писать каждый раз большие куски некрасивого кода, а писать все проще, например так:
К счастью, такая обертка уже написана и найти ее можно здесь: https://github.com/php-curl-class/php-curl-class
Просто установите ее при помощи: composer require php-curl-class/php-curl-class и не работайте с кривыми кусками кода, которые таковы вероятно потому, что cURL изначально консольное приложение.
POST и GET запросы без cURL
С помощью PHP мы можем отправить простой GET запрос используя функцию file_get_contents.
При помощи file_get_contents мы также можем отправить POST запрос.
Подробнее о том, какие опции можно передавать в stream_context_create, вы можете изучить здесь: http://docs.php.net/manual/ru/context.http.php
Другие инструменты для работы с запросами в PHP
Для работы с запросами есть еще более мощный инструмент: Guzzle
Несколько примеров на Guzzle
GET запросы на Guzzle
Разные типы запросов на Guzzle
Асинхронные запросы на Guzzle
Если интересно, то читайте: Guzzle Quick Start
Пишите комментарии, если что-то осталось не понятно.
Интеграция JavaScript cookies в CURL-запросы
В этой статье я расскажу об одной необычной проблеме, с которой мне однажды пришлось столкнуться по роду своей деятельности. Внимание: эта статья не для начинающих. Предполагается, что читатель уже имеет опыт веб-программирования и знаком с языком PHP, библиотекой CURL и основами HTTP.
Перейдем к описанию проблемы.
Мне нужно было написать скрипт бота для одного сайта с целью автоматизации некоторого процесса из нескольких шагов, не считая авторизации. Такова была задача, на первый взгляд, ничего особенного. Впрочем, поначалу так оно и было. Т.к. на сайте применялась авторизация и активно использовались cookies, было решено использовать CURL. Я понемногу сниффил HTTP-запросы к серверу сайта и воспроизводил их у себя в скрипте. Процесс, как говорится, шел…. Неприятности начались на предпоследнем шаге, когда сервер совершенно неожиданно для меня отказался выдавать желаемый результат. Это привело меня в состояние ступора, в котором я пребывал довольно долгое время, продолжая снова и снова сравнивать логи «искусственных» и «естественных» (браузерных) запросов в надежде найти хоть какое-то несовпадение. Прошло несколько часов, прежде чем я понял, что впустую трачу время.
И тогда я обратил свое внимание на так называемые JavaScript (или non-HTTP) cookies. Разумеется, CURL не мог отследить их появление и соответственно не мог добавить их в свои запросы. Но зачем серверу проверять JavaScript cookies? Хороший вопрос, в другой раз он бы обязательно меня заинтересовал, но в тот момент у меня были другие заботы.
Забегая вперед, скажу, что моя догадка оказалась верной. Сервер и в самом деле проверял JS куки, причем только на том злополучном предпоследнем шаге. Я не знаю, с какой целью это было сделано. Тем более я не уверен, что этой целью была защита от ботов. Как говорится, чужая душа (сервер) — потемки.
Первым, что пришло мне в голову, была мысль: включить опцию CURLOPT_COOKIE со строкой, составленной из параметров куков. Примерно так:
Так я и сделал: добавил эту строку в код… и очень скоро убедился, что это не работает. Вернее работает, но совсем не так как мне хотелось. В отправленном HTTP-заголовке были только куки, добавленные этой опцией, а вот куки из файла CURLOPT_COOKIEFILE при этом исчезли (исчезли из заголовка, а не из файла). Т.е. содержимое файла-хранилища куков игнорировалось. Из этого следует простой и бесполезный вывод: опции CURLOPT_COOKIE и CURLOPT_COOKIEFILE/CURLOPT_COOKIEJAR нельзя использовать вместе.
Короче, решить проблему по-быстрому не получилось. Поиск готовых решений в интернете тоже ничего не дал. Может быть я плохо искал, но все, что мне удалось найти по этой теме, вот этот вопрос, заданный на форуме StackOverflow, и как видно, оставшийся без ответа.
А тем временем срок сдачи работы подходил к концу, заказчик требовал объяснений, а у меня, как назло, куда-то пропало все мое красноречие. Тут мне почему-то вспомнилась крылатая фраза из одной советской комедии: «Либо я веду ее в загс, либо она ведет меня к прокурору». Ни в загс, ни к прокурору, мне не хотелось. Мне очень хотелось куда-нибудь скрыться и забыться… но пришлось выбирать другой способ устранения проблем.
Теперь, когда формат файла был известен, остальное было уже делом техники.
В итоге мной был написан небольшой класс CookiejarEdit, исходный код которого привожу прямо здесь:
Итак, инструмент для «продвинутой» работы с куками был готов. Но на этом мои приключения не закончились. Предстояло еще отследить те самые «значимые» JS куки, понять какие значения им присваиваются и многое другое. Но это уже другая история. А эту я пожалуй закончу. Спасибо за внимание.
P.S.:
Перечитав текст статьи в очередной раз, я понял, что ей все-таки недостает «примера из реальной жизни». Неплохо было бы, подумал я, устроить небольшую демонстрацию на примере какого-нибудь сайта. Использовать тот сайт, с которым я работал, я, по определенным причинам, не мог. Поэтому нужно было найти ему замену: какой-нибудь известный сайт, не требующий авторизации, где хоть как-то используется проверка JavaScript cookies на стороне сервера. К моему удивлению и счастью такой сайт нашелся очень быстро: в моих закладках. Это всем известный Яндекс-Каталог, категория Фриланс (то, что мне ближе всего).
Сначала эта страница выглядит так:
Но если перейти к настройкам, выбрать там пункт «стандартное с номерами»:
и вернуться на страницу каталога, то мы добъемся «чудесного» эффекта: превью со страницы исчезнут и останутся только «сухие» цифры и текст:
Давайте попробуем написать простейший бот для скачивания первой страницы этого каталога без превьюшек. Я понимаю, как глупо это выглядит со стороны: писать бота только для того чтобы изменить вид страницы. Но не забывайте, что это всего лишь пример. Давайте представим, что получение страницы без превьюшек – наше самое заветное желание).
Для начала проведем рекогносцировку. Обратим внимание на url страницы каталога после изменения настроек: он не изменился. Правда, к нему добавилась строка «?rnd=xxx», но это, по всей видимости, всего лишь указание браузеру не брать страницу из кэша. Отсюда можно сделать вывод, что настройки передаются и сохраняются, скорее всего, через куки.
Попробуем разобраться как именно это происходит. В этом нам поможет такой полезный инструмент, как Live HTTP Headers:
Это расширение Firefox’а позволяет отслеживать весь входящий и исходящий HTTP-траффик в браузере, в том числе и куки, посредством которых и осуществляется запоминание настроек в нашем примере. Происходит это, очевидно, после нажатия кнопки «Сохранить» и перехода к странице каталога.
Зайдем еще раз на страницу настроек, предварительно включив снифер Live HTTP Headers. Выберем снова пункт «стандартное с номерами» и нажмем кнопку «Сохранить». А теперь посмотрим на наш улов в снифере. Нас интересуют подробности запроса страницы каталога. У меня они имеют такой вид:
Здесь сразу бросается в глаза фрагмент «yaca_view=num». Скорее всего, это и есть наш искомый cookie-параметр. Но где он устанавливается? Во всяком случае не в заголовках ответа сервера, поскольку там этот параметр не встречается. Тогда логично предположить, что это JavaScript cookie и значит, его установка происходит где-то в яваскриптах страницы настроек («setup.xml»). Попробуем найти его в тексте этой страницы. Так и есть. Вот строка из файла «setup.xml»:
По всей видимости здесь и происходит установка параметра «yaca_view» со значением, взятым из одноименного элемента формы (в нашем случае это значение ‘num’).
Итак, мы выяснили, что для того, чтобы увидеть страницу каталога без превьюшек, нужно передать серверу cookie-параметр с именем ‘yaca_view’ и значением ‘num’. Теперь, когда у нас уже есть средство для добавления cookies в CURL-запросы, можно без особого труда написать скрипт бота. Вот его код с небольшими комментариями:
Теперь действительно все. Еще раз спасибо за внимание, особенно тем кто дочитал до конца).