Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. PHP
Code

Техники для использования cURL

by
Difficulty:IntermediateLength:LongLanguages:

Russian (Pусский) translation by Anna Goorikova (you can also view the original English article)

cURL это инструмент для передачи файлов и данных с синтаксисом URL-адресов, поддерживающий множество протоколов, включая HTTP, FTP, TELNET и т. д. Первоначально cURL был разработан как инструмент командной строки. К счастью для нас, библиотека cURL также поддерживается PHP. В этой статье мы рассмотрим некоторые дополнительные возможности cURL и способы их использования в наших PHP-скриптах.

Почему cURL?

Это правда, что есть другие способы получения содержимого веб-страницы. Много раз, в основном из-за лени, я просто использовал простые функции PHP вместо cURL:

Однако они практически не обладают гибкостью и не имеют достаточной обработки ошибок. Кроме того, есть определенные задачи, которые вы просто не можете решить, например, работа с куки-файлами, аутентификация, записи в форме, загрузка файлов и т. д.

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

Базовая структура

Прежде чем перейти к более сложным примерам, давайте рассмотрим базовую структуру запроса cURL в PHP. Существуют четыре основных шага:

  1. Инициализация
  2. Установка параметров
  3. Выполнение и получение результата
  4. Освобождение дескриптора cURL

Шаг #2 (т.е. вызовы curl_setopt()) будет большой частью этой статьи, потому что именно там происходит вся магия. Существует длинный список опций cURL, которые можно установить, которые могут подробно настроить запрос URL. Может быть, трудно пройти весь список и переварить все сразу. Поэтому сегодня мы собираемся использовать некоторые из наиболее распространенных и полезных вариантов в различных примерах кода.

Проверка на наличие ошибок

При желании вы также можете добавить проверку ошибок:

Обратите внимание, что для сравнения нужно использовать "=== FALSE" вместо "== FALSE". Поскольку нам нужно отличать пустой вывод от логического значения FALSE, что указывает на ошибку.

Получение информации

Еще один необязательный шаг - получить информацию о запросе cURL после его выполнения.

Следующая информация включена в возвращаемый массив:

  • "url"
  • "content_type"
  • "http_code"
  • "header_size"
  • "request_size"
  • "filetime"
  • "ssl_verify_result"
  • "redirect_count"
  • "total_time"
  • "namelookup_time"
  • "connect_time"
  • "pretransfer_time"
  • "size_upload"
  • "size_download"
  • "speed_download"
  • "speed_upload"
  • "download_content_length"
  • "upload_content_length"
  • "starttransfer_time"
  • "redirect_time"

Обнаружение перенаправления в браузере

В этом первом примере мы напишем сценарий, который может обнаруживать перенаправления URL-адресов на основе разных настроек браузера. Например, некоторые веб-сайты перенаправляют мобильные телефоны или даже серферы из разных стран.

Мы собираемся использовать параметр CURLOPT_HTTPHEADER для установки исходящих HTTP-заголовков, включая строку user_agent и принятые языки. Наконец, мы проверим, пытаются ли эти веб-сайты перенаправить нас на разные URL-адреса.

Сначала у нас есть набор URL-адресов для тестирования, а затем набор настроек браузера для проверки каждого из этих URL-адресов. Затем мы просматриваем эти тестовые примеры и делаем запрос cURL для каждого.

Из-за способа настройки параметров cURL возвращаемый вывод будет содержать только HTTP-заголовки (сохраненные в $output). С простым регулярным выражением мы можем видеть, включен ли заголовок "Location:".

Когда вы запускаете этот скрипт, вы должны получить такой вывод:

Отправка POST на URL-адрес

По запросу GET данные могут быть отправлены по URL-адресу через строку запроса. Например, когда вы выполняете поиск на Google, поиск термина расположен в части строки запроса URL-адреса:

Вам может не понадобиться cURL, чтобы имитировать это в веб-скрипте. Вы можете просто быть ленивым и натравить на этот url "file_get_contents()" для получения результатов.

Но некоторые HTML-формы отправляются методом POST. Когда эти формы принимаются через браузер, данные передаются через тело HTTP-запроса, вместо строки запроса. Например, если вы выполняете поиск на форумах CodeIgniter, вы будете посылать ваш поисковый запрос POST методом:

Мы можем написать PHP-скрипт для имитации такого типа URL-запроса. Сначала давайте создадим простой файл для приема и отображения данных POST. Назовем его post_output.php:

Далее создадим PHP-скрипт для выполнения cURL запроса:

Когда вы запускаете этот скрипт, вы должны получить такой вывод:

Он отправил POST скрипту post_output.php, который сбросил переменную $_POST, и мы перехватили этот вывод через cURL.

Загрузка файла

Загрузка файлов работает очень похоже на предыдущий POST пример, так как все формы загрузки файлов работают с методом POST.

Сначала давайте создадим файл для получения запроса и назовем его upload_output.php:

И вот скрипт выполнения загрузки файлов:

Когда вы хотите загрузить файл, все, что вам нужно сделать, это передать путь к файлу, как переменную post, и поставить перед ним символ @. Теперь, когда вы запускаете этот скрипт, вы должны получить такой вывод:

Multi cURL

Одной из наиболее продвинутых функций cURL является возможность создания "multi" cURL-дескриптора (набор cURL-дескрипторов). Это позволяет одновременно открывать соединения с несколькими URL-адресами и асинхронно.

При регулярном запросе cURL выполнение скрипта останавливается и ожидает завершения запроса URL-адреса до его продолжения. Если вы намереваетесь обращаться на несколько URL-адресов, это может занять много времени, так как вы можете запрашивать только один URL за раз. Мы можем преодолеть это ограничение, используя мульти дескриптор.

Давайте посмотрим на пример кода от php.net:

Идея заключается в том, что можно открыть несколько cURL дескрипторов и присвоить их одному мульти дескриптору. Затем вы можете ждать их, чтобы закончить выполнение в цикле.

В этом примере существует два основных цикла. Первый цикл do-while повторно вызывает curl_multi_exec(). Эта функция не блокирует. Он выполняется как можно меньше и возвращает значение статуса. Пока возвращаемое значение является константой "CURLM_CALL_MULTI_PERFORM", это означает, что есть еще более оперативная работа (например, отправка заголовков HTTP в URL-адреса.) Поэтому мы продолжаем вызывать его, пока возвращаемое значение не является чем-то другим.

В следующем цикле while мы продолжаем до тех пор, пока переменная $active «истинна». Это было передано как второй аргумент вызову curl_multi_exec(). Он установлен в значение «true», пока в мульти дескрипторе есть активные соединения. Следующая вещь, которую мы делаем, это вызовем curl_multi_select(). Эта функция блокируется до тех пор, пока не будет какая-либо активность соединения, например, получение ответа. Когда это произойдет, мы продолжим выполнение еще одного цикла do-while.

Давайте посмотрим, можем ли мы сами создать рабочий пример, который имеет практическую цель.

Проверка ссылок WordPress

Представьте себе блог с множеством постов, содержащих ссылки на внешние сайты. Некоторые из этих ссылок могут стать "битыми" через некоторое время по различным причинам. Возможно, страница более не существует, или весь сайт исчез.

Мы собираемся создать скрипт, который анализирует все ссылки и находит не загружающиеся веб-сайты и 404 страницы и возвращает нам отчет.

Обратите внимание, что это не будет реальный плагин Wordpress. Это всего лишь автономный скрипт, и он предназначен только для демонстрационных целей.

Так что давайте начнем. Сначала нам нужно извлечь ссылки из базы данных:

Сначала у нас есть конфигурация базы данных, за которой следует массив имен доменов, которые мы будем игнорировать ($excluded_domains). Также мы устанавливаем число для максимальных одновременных соединений, которые мы будем использовать позже ($max_connections). Затем мы подключаемся к базе данных, выбираем посты, содержащие ссылки, и собираем их в массив ($url_list).

Следующий код может быть немного сложным, поэтому я попытаюсь объяснить его небольшими шагами.

И вот объяснение для кода выше. Номера в списке соответствуют номерам в комментариях кода.

  1. Создан multi дескриптор.
  2. Мы будем создавать функции add_url_to_multi_handle() позднее. Каждый раз, когда она вызывается, она будет добавлять URL-адрес к multi дескриптору. Первоначально мы добавляем 10 (на основе $max_connections) URL-адресов к мульти дескриптору.
  3. Мы должны запустить curl_multi_exec() для первоначальной работы. Пока он возвращает CURLM_CALL_MULTI_PERFORM, есть работа. Это главным образом для создания соединений. Он не ждет полного ответа на URL.
  4. Этот основной цикл работает до тех пор, пока в мульти дескрипторе есть какая-то активность.
  5. curl_multi_select() ожидает скрипт до тех пор, пока не произойдет какое-либо действие с любым из URL-запросов.
  6. Снова мы должны позволить cURL выполнять некоторую работу, главным образом для получения данных ответа.
  7. Мы проверяем информацию. Если запрос URL был завершен, возвращается массив.
  8. Существует дескриптор cURL в возвращенном массиве. Мы используем его для получения информации о индивидуальном запросе cURL.
  9. Если ссылка была мертва или просрочена, не будет http-кода.
  10. Если ссылка была 404 страницей, http-код будет установлен в 404.
  11. В противном случае мы полагаем, что это было соединение. (Вы можете добавить дополнительные проверки для 500 кода ошибок и т.д...)
  12. Мы удаляем дескриптор cURL из мульти дескриптора, так как он больше не нужен и закрываем его.
  13. Теперь мы можем добавить еще один URL-адрес в мульти дескриптор и снова выполнить начальную работу, прежде чем двигаться дальше.
  14. Все закончено. Мы можем закрыть дескриптор multi и печатать отчет.
  15. Это функция, которая добавляет новый url к дескриптору multi. Статическая переменная $index увеличивается каждый раз, когда эта функция вызывается, так что мы можем отслеживать, где мы остановились.

Я запустил скрипт в своем блоге (с некоторыми сломанными ссылками, которые были добавлены специально, для тестирования), и вот как это выглядело:

Это заняло всего менее 2 секунд, чтобы пройти около 40 URL-адресов. Повышение производительности имеет большое значение при работе с еще большими наборами URL-адресов. Если вы одновременно открываете десять подключений, он может работать до десяти раз быстрее. Также вы можете просто использовать неблокирующий multi дескриптор curl, чтобы сделать URL-запросы без срыва вашего веб-сценария.

Некоторые другие полезные опции cURL

Аутентификация HTTP

Если на URL-адресе есть аутентификация на основе HTTP, вы можете использовать это:

Загрузка FTP

PHP имеет FTP-библиотеку, но вы также можете использовать cURL:

Использование Proxy

Можно выполнить ваш URL-запрос через прокси-сервер:

Функции обратного вызова

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

Функция обратного вызова ДОЛЖНА вернуть длину строки, что является обязательным условием для правильной работы.

Когда URL-адрес выбирается, каждый раз, когда пакет данных принимается, вызывается функция обратного вызова.

Заключение

Сегодня мы изучили мощь и гибкость библиотеки cURL. Надеюсь, эта статья вам понравилась и была полезной. В следующий раз, когда вам нужно сделать запрос URL-адреса в своем веб-приложении, рассмотрите возможность использования cURL.

Спасибо и хорошего дня!

Написать Plus учебник

Знаете ли вы, что вы можете заработать до $600 для написания учебника PLUS и/или screencast для нас? Мы ищем углубленные и хорошо написанные учебники по HTML, CSS, PHP и JavaScript. Если вы обладаете навыками, обратитесь к Джеффри на nettuts@tutsplus.com.

Обратите внимание, что фактическая компенсация будет зависеть от качества окончательного учебника и скринкаста.

Write a PLUS tutorial
  • Следуйте за нами в Твиттере или подпишитесь на Nettuts+ RSS Feed для учебных пособий по веб-разработке в Интернете.
Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.