Урок 20. Работа с cURL в PHP

В этой статье речь пойдет о таком мощном инструменте как cURL, а также о библиотеке для php, которая предоставляет доступ к этому инструменту — libcurl. Для чего все это нужно? Для связи с сервером по протоколам передачи данных, например, http или ftp. Остальные протоколы нам не особо интересны, если кто-то хочет углубляться в эту тему, то придется уже копать англоязычные ресурсы, а в этой статье будут основы и примеры использования.

Что вообще такое cURL и libcurl? Общие моменты

Итак, библиотека libcurl предоставляет нам возможность передачи данных на сервер, и получения ответов от него. Что нам это дает? Возможность эмуляции поведения пользователя или браузера! Вы можете получать содержимое страниц для последующего парсинга, можете получать заголовки ответов сервиса и программно авторизироваться на сайтах, делать скрипты постинга сообщений (например, в твиттер или на форумах) или грабберы информации. Все ограничивается лишь вашей фантазией!

Установка cURL на Denwer (Денвер). Как начать пользоваться libcurl?

Первое, что мы должны сделать, это установить библиотеку. На локальном компьютере я пользуюсь сборкой Denwer, как и подавляющее большинство начинающих вебмастеров, на которых и рассчитана статья. Опытные пользователи, которые самостоятельно устанавливают связку php+apache+mysql смогут установить и cURL, не мне объяснять им как это делается ;) А мы, новички, пользуемся готовыми решениями, чтобы было проще. Поэтому, устанавливаем libcurl следующим образом:

  • Скачиваем готовый пакет расширений «PHP5: дополнительные модули».
  • Соответственно, устанавливаем его. Ничего сложного, согласитесь :)
  • Открываем в блокноте (я всегда рекомендую Notepad++) файл:
    X:/webservers/usr/local/php5/php.ini //где X - ваш диск, куда установлен вебсервер
    

    и убираем точку с запятой в начале сроки:

    ;extension=php_curl.dll
    
  • Делаем рестарт сервера Денвер.

Готово. Чтобы проверить работоспособность библиотеки можете вызвать функцию phpinfo() и найти там строчку: cURL support enabled. Поздравляю с первой победой.

Описание cURL и первые шаги

Для началом работы с инструментом, его нужно инициализировать. Делается это следующим образом:

$ch = curl_init(); 

Мы использовали функцию инициализации сессии cURL. При этом, можно задать URL сразу, вот так:

$ch = curl_init('http://myblaze.ru'); 

А можно сделать это потом, в опциях. Порядок установки опций не имеет значения. Делается это другой функцией:

curl_setopt (resource ch, string option, mixed value)

Первый параметр этой функции, то есть resource ch мы уже создали чуть выше, а вот параметров option и value очень много. Я думаю, что не стоит копипастить сюда их все, а достаточно лишь дать ссылку на подробное описание функции, надеюсь никто не обидится: curl_setopt.

Приведу пример установки опций как раз на примере URL:

$url = "http://myblaze.ru";
curl_setopt($ch, CURLOPT_URL,$url);

Еще парочка примеров задания опций: давайте получим заголовок ответа сервера, при этом не будем получать саму страницу:

curl_setopt($ch, CURLOPT_HEADER, 1); // читать заголовок
curl_setopt($ch, CURLOPT_NOBODY, 1); // читать ТОЛЬКО заголовок без тела

Итак, мы инициализировали сессию, задали нужные нам параметры, теперь выполняем получившийся запрос, закрываем сессию и выводим результат:

$result = curl_exec($ch);  
curl_close($ch);
echo $result;

В итоге получаем наш первый полностью рабочий пример использования библиотеки libcurl:

$ch = curl_init();
$url = "http://myblaze.ru";
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_HEADER, 1); // читать заголовок
curl_setopt($ch, CURLOPT_NOBODY, 1); // читать ТОЛЬКО заголовок без тела
$result = curl_exec($ch);  
curl_close($ch);
echo $result;

Как оно работает, надеюсь, понятно, ведь мы рассмотрели каждый шаг по отдельности :) В результате мы получаем заголовок HTTP ответа от сервера, который чуть ниже обязательно разберем, чтобы лучше понимать все этапы взаимодействия браузера и сервера:

HTTP/1.1 200 OK 
Server: nginx/1.2.6 
Date: Sat, 09 Mar 2013 16:38:39 
GMT Content-Type: text/html; charset=UTF-8 
Connection: keep-alive 
Keep-Alive: timeout=10 
X-Pingback: http://myblaze.ru/xmlrpc.php 1

Великолепно! Мы получили заголовок ответа от сервера и опробовали библиотеку в действии. Чем это нам полезно? Тем, что теперь вы примерно представляете себе последовательность действий при работе с cURL:

  • Инициализировать сессию (curl_init)
  • Задать нужные нам опции (curl_setopt)
  • Выполнить полученный запрос (curl_exec)
  • Завершить сессию (curl_close)

Двигаемся дальше, но перед тем как делать с libcurl что-то более серьезное, как я и обещал, разберем подробно из чего состоит заголовок HTTP запроса к серверу и ответ на него.

Структура заголовка HTTP запроса

Для примера я обратился к странице ya.ru и в Opera Dragonfly просмотрел сформированный запрос браузера и полученный от сервера ответ. Вот и они:
Запрос
GET / HTTP/1.1 — Пытаемся получить страницу по адресу /, то есть главную, находящуюся в корне папки. Используем протокол версии 1.1.
User-Agent: Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.14 — Представляемся серверу, мы — браузер Опера.
Host: ya.ru — Доменное имя запрашиваемого ресурса.
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1 — Список допустимых форматов ресурса.
Accept-Language: ru-RU,ru;q=0.9,en;q=0.8 — Список поддерживаемых языков.
Accept-Encoding: gzip, deflate — Поддерживаемые способы кодирования.
Cookie: yandexuid=ХХХХХ — Куки, при необходимости.
Connection: Keep-Alive — Просим не разрывать соединение и оставаться на связи.
Ответ
HTTP/1.1 200 Ok — Получаем ответ с кодом 200, значит все ОК.
Server: nginx — Сервер представился — это nginx.
Date: Sun, 10 Mar 2013 14:10:50 GMT — Текущие дата и время на сервере.
Content-Type: text/html; charset=UTF-8 — Тип контента и кодировка.
Connection: close — Сервер не хочет поддерживать с нами постоянного соединения, поэтому сразу же его закрывает. Для следующего запроса будет установлено новое соединение.
Cache-Control: no-cache,no-store,max-age=0,must-revalidate — Управление кэшированием. В данном случае оно отключено.
Expires: Sun, 10 Mar 2013 14:10:50 GMT — Дата предполагаемого истечения срока действия сессии. В нашем случае оно совпадает с временем открытия, так как сервер тут же его закрыл, сразу после обработки.
Last-Modified: Sun, 10 Mar 2013 14:10:50 GMT — Время последней модификации.
Content-Encoding: gzip — Способ кодирования информации.
Полный список всех параметров, которые можно встретить в заголовке HTTP запроса можно посмотреть на википедии.
Теперь вы примерно представляете как общаются между собой ваш браузер и web-сервер. Это очень полезно знать и понимать, ведь мы будем пытаться эмулировать действия браузера с помощью библиотеки libcurl. Идем дальше.

Пример работы с библиотекой

Я считаю, что после того, как некоторые общие моменты уже ясны и вроде бы все понятно, то самое время переходить к практике и на примере уже оттачивать свое мастерство. Лично у меня всегда сразу руки чешутся все попробовать на практике :)

Раз уж cURL так хорош для парсеров, то рассмотрим функцию получения кода страницы по ее адресу. При этом на выходе получим массив с заголовком, содержимым страницы и даже коды ошибок, если что-то пойдет не так.

function get_web_page( $url )
{
  $uagent = "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.14";

  $ch = curl_init( $url );

  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);   // возвращает веб-страницу
  curl_setopt($ch, CURLOPT_HEADER, 0);           // не возвращает заголовки
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);   // переходит по редиректам
  curl_setopt($ch, CURLOPT_ENCODING, "");        // обрабатывает все кодировки
  curl_setopt($ch, CURLOPT_USERAGENT, $uagent);  // useragent
  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120); // таймаут соединения
  curl_setopt($ch, CURLOPT_TIMEOUT, 120);        // таймаут ответа
  curl_setopt($ch, CURLOPT_MAXREDIRS, 10);       // останавливаться после 10-ого редиректа

  $content = curl_exec( $ch );
  $err     = curl_errno( $ch );
  $errmsg  = curl_error( $ch );
  $header  = curl_getinfo( $ch );
  curl_close( $ch );

  $header['errno']   = $err;
  $header['errmsg']  = $errmsg;
  $header['content'] = $content;
  return $header;
}


Входные параметры:
url — адрес страницы или сайта.
Значения выходных параметров (массив с тремя элементами):
header[‘errno’] — если что-то пошло не так, то тут будет код ошибки.
header[‘errmsg’] — здесь при этом будет текст ошибки.
header[‘content’] — собственно сама страница\файл\картинка и т.д.

Используем функцию, например, так:

$result = get_web_page( "http://ya.ru" );
if (($result['errno'] != 0 )||($result['http_code'] != 200))
    {
	echo $result['errmsg'];
	}
else
	{
	$page = $result['content'];
	echo $page;
	}

Все должно пройти без ошибок и вы получите код страницы в переменной $page. Если же попробовать получить несуществующую страницу yaaaaaaaaaaaa.ru, то получим ошибку:

Could not resolve host: yaaaaaaaaaaaa.ru; Host not found

Все обрабатывается корректно и красиво :)
Дальше с кодом страницы можно делать все что угодно, например, парсить регулярками. Но это все в следующих уроках, а пока что остановимся на этом.

PHP — str_replace | Содержание | Парсер статистики Liveinternet

Комментарии:

  1. Tetsu — 03.05.2013 18:20

    Можете ли вы сообщить сколько еще уроков вы собираетесь сделать и на какие темы они будут?

  2. myblaze 03.05.2013 22:49

    Tetsu, буду писать пока будет время :) Есть какие то пожелания?

  3. Tetsu — 04.05.2013 05:31

    Не совсем… просто хотелось бы освоить это дело побыстрее, поэтому и интересуюсь какие еще темы мне стоит изучить в продолжение этим.

  4. Alex — 09.08.2013 18:31

    А на MAC OS X нассали? У меня MAMP, что мне делать?

  5. Kostya — 09.09.2013 04:48

    Автор, спасибо огромное всё сразу стало на свои места в голове:)

  6. myblaze 09.09.2013 16:26

    Не за что )

  7. Valek — 11.11.2013 01:08

    Привет
    Забыл ты про функцию iconv у меня бяки отобразились
    Есть парочка тем если интересно.
    1)Чем отличаются echo от print(понимаю что тема затерта в нете но вот подробностей так и не встречал)
    Если хочешь я могу тебе написать массу огромную тем по которой не только мне интересно будет, но и публике тоже интересно будет!
    И еще вот что еще….Спасибо за урок очень хороший но очень сжат,мне кажется что новичку (совсем начинающему)будет трудновато понять что и как делается.

  8. Михаил — 21.11.2013 17:08

    Большое спасибо. Помог очень))

    Всем остальным, кто не дружит с регулярками, хочу посоветовать PHP Simple HTML DOM Parser.
    http://habrahabr.ru/post/176635/

  9. Виктория — 15.01.2014 00:11

    Зравствуйте!

    У меня, как и у Valek, вылезли кракозябры (с кодировкой проблемы). Valek написал про функцию
    string iconv ( string $in_charset , string $out_charset , string $str )
    но я никак не могу с ней разобраться. Как понять из какой кодировки в какую переделывать (первые два параметра), чтобы получился нормальный русский язык?

  10. myblaze — 15.01.2014 12:43

    проверьте, точно файл сохранен в кодировке UTF-8? В коде страницы присутствует meta-тег content=»text/html; charset=UTF-8″? И в заключении, после всего этого в самом браузере стоит автоопределение кодировки или жестко задана (может там, например, windows-1251)?

  11. Михаил — 19.01.2014 14:24

    Виктория, myblaze дело говорит. Ещё раз повторюсь, если позволите.
    1) Чтобы узнать кодировку html документа, нужно посмотреть в сам html документ и обратить внимание на тег
    2) Возможно вы пытаетесь вывести эту строку без учёта её кодировки. Советую сохранить в файл и просмотреть через файл эту строку. Возможно в файле всё откроется без кракозябр.
    3) Советую скачать текстовый редактор Notepad++. Там в меню есть возможность преобразовать и перекодировать. Поэкспериментируйте. Скопируйте и вставте свои кракозябры и попробуйте преобразовать или перекодировать. После каждой неудачной перекодировки нужно заново открывать файл. Это поможет быстрей разобраться с кодировками.

  12. Jack — 31.01.2014 21:26

    >>Alex — 09.08.2013 18:31
    А на MAC OS X нассали? У меня MAMP, что мне делать?
    —————-
    Для начала научится гуглить, у меня тоже мак c MAMP и проблемы найти мануал по подключению curl не составило труда.

  13. myblaze 01.02.2014 09:30

    Jack, кто ищет, тот всегда найдет ;) А Aleх’у только удачи пожелать можно, может тоже когда-нибудь научится гуглить.

  14. Сергей — 03.10.2014 11:43

    Спасибо!

  15. М — 10.04.2015 12:44

    Спасибо

  16. Денис — 24.01.2017 15:06

    Возникает проблема с Curl, когда сайт находится на сервере http выдается пустой лист, если смотрим смотри ошибки — culdnt connect to host, что делать?

Добавить комментарий