Curl запрос как из браузера
GET запрос при помощи cURL
cURL - мощный инструмент для отправки запросов. Только взгляните сколько он всего умеет.
Все настройки, которые вы можете найти по этой ссылке. Там вы найдете опции, которые мы будем устанавливать функцией curl_setopt, в дальнейших примерах.
Пример простого GET запроса при помощи cURL:
В итоге, переменная $result снова содержит html код страницы этого сайта.
- CURLOPT_VERBOSE - установлена в true для вывода дополнительной информации. Записывает вывод в поток STDERR, или файл, указанный параметром CURLOPT_STDERR.
- CURLOPT_RETURNTRANSFER - установлена в true, для того чтобы вернуть ответ сервера. Если вам ответ сервера не нужен, то можете убрать эту опцию.
Если в результате сервер вернет нам редирект, то мы по нему автоматически не перейдем. А иногда это бывает полезно. Чтобы cURL автоматически шел по редиректу нужно установить опцию CURLOPT_FOLLOWLOCATION.
С установленной опцией скрипт автоматически перейдет по вернувшемуся редиректу и вернет ответ уже с итоговой страницы.
POST запрос при помощи cURL
Отлично, с GET и POST запросами в cURL мы немного освоились. Теперь разберемся с заголовками, которые мы можем отсылать в запросе.
cURL: POST запрос в формате JSON
Отличия конфигурации JSON запроса от обычного POST запроса заключается в том, что мы кодируем поля при помощи json_encode() И добавляем заголовок Content-Type: application/json
cURL: GET запрос в формате JSON
GET запрос в формате JSON отправляется так же как и POST запрос, просто нужно CURLOPT_CUSTOMREQUEST установить в 'GET'
А в остальном код идентичен предыдущему примеру. Хотя, надо признать, GET запросы с телом - это нонсенс. Обычно для этих целей используется POST, PUT или PATCH, но был у меня один случай. Поэтому вот GET запрос в формате JSON.
Стоп, Дмитрий, прекрати выдумывать виды запросов!
Это делается по тому же принципу, как и 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 адресов:
И если мы будем по очереди отправлять запросы, то второй запрос начнется только после того, как закончился первый и так далее, а это существенно увеличивает время работы скрипта.
Выглядит это так:
Теперь в $results у нас содержится массив, где ключи - это url адреса, а значения - результаты запросов. Однако запросы выполняются долго. Но мы можем это ускорить.
Как выполнить 3 запроса одновременно? В этом нам поможет curl_multi_
Такие параллельные запросы выполняются значительно быстрее чем поочередные.
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
OAuth авторизация
Авторизация через форму
Допустим на сайте есть такая форма:
Тогда наш cURL запрос должен быть сформирован так:
Автоматическое построение запросов
Перевод консольной команды curl в PHP
Так вы можете создать простые запросы на cURL в PHP не создавая их вручную.
Лайфхак
В консоли браузера, во вкладке сеть, вы можете кликнуть правой кнопкой мыши и скопировать любой запрос в виде команды cURL, а потом с помощью сервиса curl-to-php перевести запрос в PHP. Теперь вы вообще можете сконвертировать в cURL абсолютно любой запрос, который посылает ваш браузер.
Как работать с cURL гораздо проще
Вы можете спросить: почему у cURL такие кривые и страшные методы? У вас может возникнуть желание взять и создать обертку для работы с cURL, чтобы вы могли не писать каждый раз большие куски некрасивого кода, а писать все проще, например так:
Просто установите ее при помощи: composer require php-curl-class/php-curl-class и не работайте с кривыми кусками кода, которые таковы вероятно потому, что cURL изначально консольное приложение.
POST и GET запросы без cURL
Теперь у нас в переменной $result записан весь html код главной страницы этого сайта. Мы совершили GET запрос, а html код - это ответ на него.
Как видите file_get_contents - полезная функция, которая не только позволяет читать файлы на нашем сервере, но еще и отправлять запросы.
I'm trying to simulate a real browser request using CURL with proxy rotate, I searched about it, But none of the answers worked.
Here is the code:
Here is what I get when I run the script:
As well as a Recaptcha, As it says:
When I visit the website using any browser, The website is displayed.
But with the above script, It's not.
So what am I missing to make the curl request like a real browser request and not be detected as a bot?
Or if there is an API/library that could do it, Please mention it.
Would Guzzle or similar fix this issue?
@ArtisticPhoenix, You are right, It's a typo error while copying/pasting the code, I updated the question
1 Answer 1
"So what am I missing to make the curl request like a real browser request"
My guess is they are using a simple cookie check. There are more sophisticated methods that allow recognizing automation such as cURL with a high degree of reliability, especially if coupled with lists of proxy IP addresses or IPs of known bangers.
Your first step is to intercept the outgoing browser request using pcap or something similar, then try and replicate it using cURL.
One other simple thing to check is whether your cookie jar has been seeded with some telltale. I routinely do that too, since most scripts on the Internet are just copy-pastes and don't pay much attention to these details.
The thing that would for sure make you bounce from any of my systems is that you're sending a referer, but you don't seem to actually have connected to the first page. You're practically saying "Well met again" to a server that is seeing you for the first time. You might have saved a cookie from that first encounter, and the cookie has now been invalidated (actually been marked "evil") by some other action. At least in the beginning, always replicate the visiting sequence from a clean slate.
You might try and adapt this answer, also cURL-based. Always verify actual traffic using a MitM SSL-decoding proxy.
Now, the real answer - what do you need that information for? Can you get it somewhere else? Can you ask for it explicitly, maybe reach an agreement with the source site?
Простым языком об использовании PHP с cURL на одном примере сайта с JavaScript-защитой.
1. Парсер для получения контента по ссылкам
Задача парсера тривиальная - агрегатор новостей: сбор контента с новостных сайтов.
На входе: файл с URL-ссылками на статьи для сбора.
Веб-интерфейс для администратора: php-страница с кнопкой для запуска скрипта парсера.
Скрипт: использование cURL - с минимальным набором опций.
заходит на страницу запуска скрипта,
нажимает кнопку запуска.
обходит (в цикле) массив ссылок на сайты,
собирает контент статей,
формирует веб-страницы по заданному шаблону.
Проблема: наткнувшись на интересную статью с сайта о недвижимости (Домофонд), попытался добавить ее в файл ссылок для сбора контента.
Контент со страницы не собрался: 403 Forbidden.
Спойлер: если сразу интересно найденное решение, то можно переходить к заключению, пропустив бесплодные попытки поиска.
2. Попытка решения в лоб за счет "имитации" браузера доп. заголовками в запросе
В поисках сначала натолкнулся на статьи о том, что некоторые сайты ставят защиту от ботов (чем и является парсер для сбора контента). Например, при использовании cURL надо "оживлять" запрос заголовками, что я и делал, но безуспешно - проиллюстрирую одной из попыток.
2.1. Заголовок с Host
Хотя при добавлении хост-заголовка все же возникла одна из мыслей.
Поэтому в браузере я вручную открывал страницу с/без www - естественно, визуально для меня ничего не менялось.
Перенаправление срабатывало нормально, но потом я еще решил изменить и протокол, чтобы проверить, какой будет редирект.
При этом вместо статьи отобразилась та же ошибка: 421 Misdirected Request.
3. Изучение веб-страницы, "проблемной" для парсера
Продолжив поиски по теме защиты на сайтах от ботов, столкнулся с выполнением JavaScript-кода на страницах для этой цели.
Сразу скажу, что в браузере отключил выполнение JavaScript-сценариев, но страница продолжила отображаться нормально.
Хотя при изучении кода проблемной страницы смутил следующий скрипт, включающий в виде JSON-блока контент статьи.
4. ПО для сбора контента с веб-сайтов
В ходе исследований попадались статьи на "безголовые" браузеры, среды наподобие селениума и т.п.
Предлагалась имитация действий пользователя, установка тайм-аутов при обращении к сайту для снижения нагрузки и т.д.
Но для решения задач по парсингу одной-двух ссылок, а не многопоточного скачивания всего сайта это не подходило.
Глубоко в этом направлении не разбирался и не копал.
5. Возврат к мысли про ссылку с IP-адресом сервера
Пришлось вернуться к начальному вопросу: как получить контент веб-страницы, если по ссылке с именем хоста не получилось.
В ответ получил содержимое страницы.
6. Выводы и решение
В чем проблема - до конца непонятно. Закроет ли собственник сайта (Домофонд) эту дыру и сможет ли это вообще сделать - неясно.
Но в статье приведено достаточно простое решение и оно работает, а на просторах интернета с такой легкой подсказкой я не сталкивался.
В решении дополнил скрипт методом gethostbyname, чтобы получать IPv4-адрес, соответствующий переданному имени хоста.
Парсер для получения контента по ссылке на входе имеет тот же набор URL-ссылок, но теперь обращается по IP-адресам серверов, что не мешает его работе в сборе данных.
Нужно получить 100 первых результатов поиска по определенному ключевому слову(при помощи скрапера), но время от времени гугл блокирует IP и требует ввести каптчу. Можно ли эмулировать браузерный запрос при помощи cURL?
- Вопрос задан более трёх лет назад
- 8901 просмотр
Это лишнее для таких запросов как у автора, лишняя трата памяти, и придется что-то выдумывать с оберткой для запуска в несколько потоков.
1. Сделайте запрос в браузере
2. Посмотрите какие заголовки уходят к гуглу (смотреть с помощью chrome dev tools, firebug, fiddler или т.п.)
3. Запрограммируйте curl отправлять идентичные заголовки
4.…
5. PROFIT!
Предположим вы передадите заголовки браузера, а что это изменит? Google также будет блокировать при превышении неких лимитов.
В том то и дело, что при curl запросе google требует ввести каптчу, но при переходи на нужный url в браузере каптчу вводить не надо
Этого будет достаточно, пока не будут превышены пороговые значения. Обычные пользователи иногда страдают из-за этого, т.к. вместо поиска выводится запрос на ввод капчи.
Гугл ведь неспроста блокирует запросы от скриптов, и проверяет их капчей, поэтому нужно доказать ему, что ваш скрипт — не бот (распознать капчу). Я замечал, что он это делает, когда запрашиваемые слова не связаны морфологически и идут массово с одного адреса (который, к тому же, наверняка принадлежит известному датацентру?). Еще можно попробовать отправлять корректный «браузерный» заголвок, с юзерагентом и прочими хедерами.
Какая Гуглу выгода от того, что им пользуются боты? Они не смотрят рекламу, от них только нагрузка и вред. правильно Гугл делает, я бы тоже скрипты блокировал.
Предварительные сведения
Используя ключ -v , можно увидеть, какие именно команды curl отсылает серверу. Этот ключ дает возможность разобраться в особенностях взаимодействия curl и веб-сервера и помогает отладить запрос.
Формы
Справка
Справку по curl можно получить, набрав в командной строке
$ — приглашение командной строки.
Получить содержимое страницы (GET)
вы получите веб-страницу, выведенную в окно терминала (точнее, в стандартный вывод). Чтобы сохранить эту страницу в файл curl.html , нужно указать
Форма запроса может использовать метод GET. Например, так:
Для формирования GET-запроса, введите то, что ожидалось от формы:
Метод POST
Форма, генерирующая POST-запрос, отличается от предыдущей лишь методом отправки:
curl сформирует POST-запрос с теми же данными следующим образом:
Обратите внимание на то, что данные, которые вы отправляете серверу, должны быть правильно закодированы. curl не сделает этого за вас. К примеру, если вы хотите, чтобы данные содержали пробел, то вам нужно заменить этот пробел на %20 и т. п. Это одна из самых распространенных ошибок, в результате чего данные передаются не так, как нужно.
Загрузка файлов с помощью POST
Форма, с помощью которой пользователь может загрузить файл, выглядит примерно так:
Заметьте, что тип содержимого Content-Type установлен в multipart/form-data .
Чтобы с помощью curl отослать данные в такую форму, введите:
Скрытые поля формы
Скрытые поля в формах являются одним из наиболее распространенных способов передачи информации о состоянии HTML-приложения. Такие поля не заполняются, они невидимы для пользователя, но передаются так же, как и обычные поля.
Пример формы с одним видимым и одним скрытым полями:
Как выглядит POST-запрос "изнутри"
Когда с помощью curl вы заполняете форму и отсылаете ее данные на сервер, вы наверняка хотите, чтобы сформированный curl POST-запрос выглядел так же, как если бы он был выполнен с помощью браузера.
Простейший способ увидеть свой POST-запрос заключается в следующем:
Вы увидите, что данные присоединились к URL и разделены символами ? , как это и предполагается при использовании GET-форм.
Комментарии
Дмитрий Храмов
Компьютерное моделирование и все, что с ним связано: сбор данных, их анализ, разработка математических моделей, софт для моделирования, визуализации и оформления публикаций. Ну и за жизнь немного.
Читайте также: