В статье рассмотрены пример использования библиотеки cURL необходимой для передачи данных по протоколам HTTP, HTTPS, FTP. cURL - клиентская библиотека работы с URL, используется в языке PHP для передачи и получения различных данных форматах, JSON, XML, обычном HTML, а так же получения, парсинга и загрузки файлов.
В общем виде работа cURL выглядит так:
Инициализация сеанса -> Настройка запроса -> Выполнение запроса -> Закрытие сеанса.
Настройки запроса cURL
Для настройки запроса существует набор специальных параметров, а именно:
-
CURLOPT_RETURNTRANSFER - вернуть ответ в виде строки, вместо того, чтобы показывать его сразу
-
CURLOPT_CONNECTTIMEOUT - сколько по времени ждать ответа
-
CURLOPT_TIMEOUT - сколько секунд будет выполняться cURL запрос
-
CURLOPT_USERAGENT- headers (заголовки) для запроса
-
CURLOPT_URL - URL куда будет отправлен запрос
-
CURLOPT_POST - отправить POST запрос
-
CURLOPT_POSTFIELDS - массив POST полей к запросу
Функции cURL
Основные функции которыми вам придётся пользоваться во время работы:
curl_init()
- открывает сеанс cURL
-
curl_close()
- закрывает сеанс cURL
-
curl_exec()
- выполняет запрос
И так, давайте рассмотрим самые частые случаи использования этой замечательной библиотеки.
GET запрос
Получаем страницу сайта
//Инициализация сеанса
$ch = curl_init('https://site.com');
//Установка параметров
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
//Выполнение
$html = curl_exec($ch);
//Закрытие сеанса
curl_close($ch);
//Работа с полученными данными
echo $html;
GET запрос с параметрами
Теперь передадим пару параметров
//Подготовка массива спараметрами
$getParams = [
'name' => 'Max',
'age' => '21'
];
$ch = curl_init('https://site.com?' . http_build_query($getParams));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$html = curl_exec($ch);
curl_close($ch);
echo $html;
POST запрос
//Допустим отправлям оценку (количество звёзд) этому материалу
$arr = [
'post_id' => '123',
'stars' => '5'
];
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_POST, 1); //Этой опцией мы указали, что запрос должен быть выполнен методом POST
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($arr, '', '&'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$html = curl_exec($ch);
curl_close($ch);
echo $html;
Отправка JSON средствами POST и cURL
//Подготовка данных
$user = [
'user' => 'Max',
'age' => 25,
'position' => 'Manger'
];
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type:application/json']);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($user, JSON_UNESCAPED_UNICODE)); //Конвертируем данные в JSON
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$res = curl_exec($ch);
curl_close($ch);
//Обратная конвертация (ответ так же получен в формате JSON)
$res = json_decode($res, true);
//Удобно просматриваем массив
echo '<pre>'; print_r($res); echo '</pre>';
Большинство ajax форм на сайте отправляют данные и принимают ответ со стороны сервера именно в формате JSON
PUT запрос
HTTP-метод PUT используется в REST API для обновления данных, хотя обычно все забивают и пользуются POST-ом.
//Подготовка данных
$data = [
'user' => 'Max',
'age' => 26,
'position' => 'Marketolog'
];
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data, '', '&'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$html = curl_exec($ch);
curl_close($ch);
echo $html;
DELETE запрос
Ещё один метод, который используется в REST API и служит для удаления данных.
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
curl_close($ch);
Запрос через proxy сервер
Иногда нужно послать запрос через сторонний шлюз, чтобы не палиться, например во время парсинга сайтов
//Параметры proxy сервера
$proxy = '192.168.155.214';
$proxyPort = '8000';
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_TIMEOUT, 400);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
curl_setopt($ch, CURLOPT_PROXYPORT, $proxyPort);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$html = curl_exec($ch);
curl_close($ch);
Отправка файлов на удалённый сервер
Для отправки файлов используется метод POST. Старые варианты отправки до php 5.5 рассматривать не будем, т.к. на дворе 2023, везде используется минимум php 7 и уже активно продвигается php 8.1.
Для отправки файл через cURL используется специальная функция
curl_file_create() принимающая 3 аргумента:
- filename - путь к файлу, который будет загружен
- mime_type - mime-тип файла.
- posted_filename - имя файла при отправке методом POST.
$curl_file = curl_file_create(__DIR__ . '/img.png', 'image/png' , 'img.png');
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['images' => $curl_file]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$res = curl_exec($ch);
curl_close($ch);
Для отправки нескольких файлов сразу, в $curl_files можно передать массив полей.
$curl_files = [
'images[0]' => curl_file_create(__DIR__ . '/img.png', 'image/png' , 'img.png'),
'images[1]' => curl_file_create(__DIR__ . '/img2.png', 'image/png' , 'img2.png')
];
Так же файлы можно передать методом PUT:
$file = __DIR__ . '/avatar.jpg';
$fp = fopen($file, 'r');
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_UPLOAD, true);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($file));
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
curl_close($ch);
Скачивание файлов
Если в параметр CURLOPT_FILE передать указатель на открыты при помощи fopen() файл, cURL сразу сохранит полученные данные в этот файл.
$file_name = __DIR__ . '/page.html';
$file = @fopen($file_name, 'w');
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_FILE, $file);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
curl_close($ch);
fclose($file);
Либо используйте проверенный временем
file_put_contents()
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$html = curl_exec($ch);
curl_close($ch);
file_put_contents(__DIR__ . '/page.html', $html);
Отправить и получить cookie
Если вам нужно, чтобы cURL сохранил cookie в файл, пропишите его адрес в параметрах
CURLOPT_COOKIEFILE
и
CURLOPT_COOKIEJAR
.
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_COOKIEFILE, __DIR__ . '/cookie_file.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, __DIR__ . '/cookie_file.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$html = curl_exec($ch);
curl_close($ch);
А для передачи значения cookie, используйте параметр
CURLOPT_COOKIE
.
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_COOKIE, 'param_name=param_value');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$html = curl_exec($ch);
curl_close($ch)
Мимикрируем под браузер
Иногда пред программистом встаёт задача спарсить какой-то сайт, например справочник товаров партнёра (часто партнёры интернет-магазинов не имеют вменяемых материалов для передачи), но многие сайты защищены от парсинга средствами сервера. Они отличают сеанс реального пользователя от запросов с cURL проверяя такие параметры как UserAgent, Referer и другие. Если их не передать специально, сервер вернёт ошибку 404 или 500 и не позволит вам спарсить страницу. Чтобы нам имитировать браузер при запросах к сайту, необходимо передать набор заголовков присущих браузеру реального посетителя. Например:
$headers = [
'cache-control: max-age=0',
'upgrade-insecure-requests: 1',
'user-agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36',
'sec-fetch-user: ?1',
'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
'x-compress: null',
'sec-fetch-site: none',
'sec-fetch-mode: navigate',
'accept-encoding: deflate, br',
'accept-language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7',
];
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_COOKIEFILE, __DIR__ . '/cookie_file.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, __DIR__ . '/cookie_file.txt');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, true);
$html = curl_exec($ch);
curl_close($ch);
echo $html;
В особых случаях, можно даже написать функцию и собирать массив
$headers
налету, под каждый запрос. Пусть сайт думает что его посещают разные люди.
HTTP Авторизация средствами cURL
Basic Authorization
Если на сайте настроена HTTP авторизация, например чере .htpasswd, войти на сайт, можно при помощи параметра
CURLOPT_USERPWD
.
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_USERPWD, 'login:password');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$html = curl_exec($ch);
curl_close($ch);
echo $html;
OAuth авторизация
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: OAuth TOKEN']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$html = curl_exec($ch);
curl_close($ch);
echo $html;
Получить HTTP код ответа сервера
Про коды ответа веб-сервера можно почитать в
этой статье.
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $http_code; // Если сайт доступен, выведет код: 200
Если CURL возвращает false
В случае если запрос к ресурсу через cURL вернул false, произошла какая-то ошибка, чтобы узнать что именно случилось нужно воспользоваться следующими фунциями:
curl_errno()
- возвращает код последней ошибки
-
curl_strerror()
- получить текстовое описание для кода ошибки
$ch = curl_init('https://site.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
$res = curl_exec($ch);
var_dump($res); //получили false
if ($errno = curl_errno($ch)) {
$message = curl_strerror($errno);
echo 'cURL error (' . $errno . '): ' . $message; //Выведет код и текстовое описание ошибки
}
curl_close($ch);
Библиотеки
Чтобы упросить работу с HTTP запросами, можно воспользоваться готовым решением, библиотекой
Guzzle. Она позволяет избежать громоздкого написания кода, быстро и удобно отправлять данные нужным способом (GET, POST и т.п.). Имеет в своём арсенале много удобных методов, позволяющих получать мета-информацию о запросах.
$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.github.com/user', [
'auth' => ['user', 'pass']
]);
echo $res->getStatusCode();
// "200"
echo $res->getHeader('content-type')[0];
// 'application/json; charset=utf8'
echo $res->getBody();
// {"type":"User"...'
Так же предусмотрена работа с асинхронными запросами
// Send an asynchronous request.
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
$promise = $client->sendAsync($request)->then(function ($response) {
echo 'I completed! ' . $response->getBody();
});
$promise->wait();
Пользуйтесь готовыми примерами cURL или целыми библиотеками. Удачи!