cURL — это инструмент, который использует синтаксис URL для передачи файлов и данных. Он поддерживает множество протоколов, таких как HTTP, FTP, TELNET и т. д. Самое приятное то, что php также поддерживает библиотеку cURL. В этой статье будут представлены некоторые расширенные возможности cURL и способы их использования в PHP.
Зачем использовать cURL?
Да, мы можем получить веб-контент другими способами. Большую часть времени, из-за лени, я просто использую простую функцию PHP:
$content = file_get_contents(" http://www.bizhicool.com ");
// или
$lines = file(" http://www.bizhicool.com ");
// или
readfile( http://www.bizhicool.com ); Однако этому подходу не хватает гибкости и эффективной обработки ошибок. Более того, вы не можете использовать его для выполнения некоторых сложных задач, таких как обработка файлов cookie, проверка, отправка форм, загрузка файлов и т. д.
cURL — это мощная библиотека, которая поддерживает множество различных протоколов и опций и может предоставлять различную информацию, связанную с URL-запросами.
Базовая структура Прежде чем изучать более сложные функции, давайте рассмотрим основные этапы настройки запроса cURL в PHP:
Инициализируйте, установите переменные, выполните и получите результаты, освободите дескриптор cURL.
// 1. Инициализация
$ch = Curl_init();
// 2. Установка параметров, включая URL
Curl_setopt($ch, CURLOPT_URL, " http://www.bizhicool.com ");
Curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, 1);
Curl_setopt ($ ch, CURLOPT_HEADER, 0);
// 3. Выполнить и получить содержимое HTML-документа
$output = curl_exec($ch);
// 4. Освободить дескриптор скручивания
Curl_close($ch); Второй шаг (то есть, Curl_setopt()) является самым важным, и здесь кроется вся тайна. Существует длинный список параметров cURL, которые можно установить, которые определяют различные детали запроса URL. Прочитать и понять их все одновременно может быть сложно, поэтому сегодня мы попробуем только наиболее распространенные и полезные варианты.
Проверка ошибок Вы можете добавить оператор проверки ошибок (хотя это не обязательно):
// ...
$output = curl_exec($ch);
если ($выход === ЛОЖЬ) {
echo "Ошибка cURL: " .
}
// ...Обратите внимание, что при сравнении мы используем «=== FALSE» вместо «== FALSE». Потому что мы должны различать пустой вывод и логическое значение FALSE, которое и является настоящей ошибкой.
Получить информацию. Это еще один необязательный параметр, который позволяет получить информацию об этом запросе после выполнения cURL:
// ...
Curl_exec ($ ч);
$info = curl_getinfo($ch);
echo 'Get'. $info['url'] 'Требуется время'. $info['total_time'] 'Секунды';
// ...возвращенный массив содержит следующую информацию:
"url" //Сетевой адрес ресурса
"content_type" //Кодировка контента
"http_code" //код состояния HTTP
"header_size" //Размер заголовка
"request_size" //Размер запроса
"filetime" //Время создания файла
"ssl_verify_result" //Результат проверки SSL
"redirect_count" //Технология перехода
"total_time" //Общее затраченное время
"namelookup_time" //время DNS-запроса
"connect_time" //Ожидание времени подключения
"pretransfer_time" //Время подготовки перед передачей
"size_upload" //Размер загружаемых данных
"size_download" //Размер загружаемых данных
"speed_download" //Скорость загрузки
"speed_upload" //Скорость загрузки
"download_content_length" //Длина загружаемого контента
"upload_content_length" //Длина загружаемого контента
"starttransfer_time" //Время начала передачи
"redirect_time" //Перенаправление требует времени. Перенаправление на основе браузера. В первом примере мы предоставим фрагмент кода, который определяет, имеет ли сервер перенаправление на основе браузера. Например, некоторые веб-сайты перенаправляют веб-страницы в зависимости от того, мобильный ли это браузер или даже из какой страны находится пользователь.
Мы используем параметр CURLOPT_HTTPHEADER для установки заголовков HTTP-запросов, которые мы отправляем (заголовки HTTP), включая информацию пользовательского агента и язык по умолчанию. Затем мы посмотрим, перенаправляют ли нас эти конкретные веб-сайты на разные URL-адреса.
// URL для тестирования
$urls = массив(
" http://www.cnn.com ",
" http://www.mozilla.com ",
" http://www.facebook.com "
);
// Информация о браузере для тестирования
$браузеры = массив(
"стандартный" => массив (
"user_agent" => "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729)",
"язык" => "en-us,en;q=0.5"
),
"iphone" => массив (
"user_agent" => "Mozilla/5.0 (iPhone; U; процессор, как Mac OS X; en) AppleWebKit/420+ (KHTML, например Gecko) Версия/3.0 Mobile/1A537a Safari/419.3",
"язык" => "ru"
),
"французский" => массив (
"user_agent" => "Mozilla/4.0 (совместимый; MSIE 7.0; Windows NT 5.1; GTB6; .NET CLR 2.0.50727)",
"language" => "fr,fr-FR;q=0.5"
)
);
foreach ($urls как $url) {
echo "URL: $urln";
foreach ($browsers as $test_name => $browser) {
$ch = Curl_init();
//Установить URL
curl_setopt($ch, CURLOPT_URL, $url);
//Устанавливаем заголовки, специфичные для браузера
curl_setopt($ch, CURLOPT_HTTPHEADER, массив(
"Агент пользователя: {$browser['user_agent']}",
"Accept-Language: {$browser['language']}"
));
// Содержимое страницы нам не нужно
curl_setopt($ch, CURLOPT_NOBODY, 1);
// Просто возвращаем HTTP-заголовок
Curl_setopt ($ ch, CURLOPT_HEADER, 1);
// Возвращаем результат вместо того, чтобы печатать его
Curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
локон_закрыть ($ ч);
// Есть ли какая-либо информация HTTP-заголовка для перенаправления?
if (preg_match("!Location: (.*)!", $output, $matches)) {
echo "$test_name: перенаправляет на $matches[1]n";
} еще {
echo "$test_name: нет перенаправленияn";
}
}
эхо "nn";
}Сначала мы создаем набор URL-адресов, которые необходимо протестировать, а затем указываем набор данных браузера, которые необходимо протестировать. Наконец, цикл используется для проверки различных ситуаций сопоставления URL-адресов и браузеров, которые могут возникнуть.
Поскольку мы указали опцию cURL, возвращаемые выходные данные включают только информацию HTTP-заголовка (хранящуюся в $output). Используя простое регулярное правило, мы проверяем, содержит ли информация заголовка слово «Location:».
Запуск этого кода должен вернуть следующие результаты:
Отправка данных с использованием метода POST При выполнении запроса GET данные могут быть переданы на URL-адрес через «строку запроса». Например, при поиске в Google ключ поиска является частью строки запроса URL-адреса:
http://www.google.com/search?q=nettuts В этом случае вам, вероятно, не понадобится cURL для моделирования. Передача этого URL-адреса в «file_get_contents()» даст тот же результат.
Однако некоторые HTML-формы отправляются с использованием метода POST. При отправке этой формы данные отправляются через тело HTTP-запроса (тело запроса) вместо строки запроса. Например, при использовании формы форума CodeIgniter, независимо от того, какие ключевые слова вы вводите, вы всегда будете отправлены на следующую страницу:
http://codeigniter.com/forums/do_search/ Вы можете использовать сценарий PHP для имитации этого URL-запроса. Сначала создайте новый файл, который может принимать и отображать данные POST. Мы назовем его post_output.php:
print_r($_POST); Затем напишите PHP-скрипт для выполнения запроса cURL:
$url = " http://localhost/post_output.php ";
$post_data = массив (
"фу" => "бар",
"запрос" => "Неттуц",
"действие" => "Отправить"
);
$ch = Curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
Curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, 1);
// Мы публикуем данные!
Curl_setopt ($ ch, CURLOPT_POST, 1);
//Добавляем переменную сообщения
Curl_setopt ($ ch, CURLOPT_POSTFIELDS, $ post_data);
$output = curl_exec($ch);
локон_закрыть ($ ч);
echo $output;После выполнения кода вы должны получить следующие результаты:
Этот скрипт отправляет POST-запрос в post_output.php, переменную $_POST страницы, и возвращает его. Мы фиксируем этот вывод с помощью cURL.
Загрузка файлов Загрузка файлов очень похожа на предыдущий POST. Потому что все формы загрузки файлов отправляются методом POST.
Сначала создайте новую страницу для получения файлов с именем upload_output.php:
print_r($_FILES);Ниже приведен сценарий, который фактически выполняет задачу загрузки файла:
$url = " http://localhost/upload_output.php ";
$post_data = массив (
"фу" => "бар",
//Локальный адрес файла для загрузки
"upload" => "@C:/wamp/www/test.zip"
);
$ch = Curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
Curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, 1);
Curl_setopt ($ ch, CURLOPT_POST, 1);
Curl_setopt ($ ch, CURLOPT_POSTFIELDS, $ post_data);
$output = curl_exec($ch);
локон_закрыть ($ ч);
echo $output; Если вам нужно загрузить файл, просто передайте путь к файлу как переменную сообщения, но не забудьте добавить символ @ впереди. Выполнение этого сценария должно привести к следующему выводу:
Пакетная обработка cURL (мульти cURL)
cURL также имеет расширенную функцию — пакетные дескрипторы. Эта функция позволяет открывать несколько URL-соединений одновременно или асинхронно.
Вот пример кода с php.net:
//Создаем два ресурса cURL
$ch1 = Curl_init();
$ch2 = Curl_init();
//Указываем URL и соответствующие параметры
Curl_setopt($ch1, CURLOPT_URL, " http://lxr.php.net/ ");
Curl_setopt ($ ch1, CURLOPT_HEADER, 0);
Curl_setopt($ch2, CURLOPT_URL, " http://www.php.net/ ");
Curl_setopt ($ ch2, CURLOPT_HEADER, 0);
//Создаем дескриптор пакета cURL
$mh = curl_multi_init();
//Добавляем первые два дескриптора ресурса
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);
// Предварительно определяем переменную состояния
$актив = ноль;
//Выполняем пакетную обработку
делать {
$mrc = curl_multi_exec($mh, $active);
} Пока ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
делать {
$mrc = curl_multi_exec($mh, $active);
} Пока ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
//Закрываем каждый дескриптор
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
Curl_multi_close($mh); Здесь вам нужно открыть несколько дескрипторов cURL и назначить их дескриптору пакета. Затем вы просто ждете завершения цикла while.
В этом примере есть два основных цикла. Первый цикл do- while повторно вызывает функцию Curl_multi_exec(). Эта функция неблокирующая, но будет выполняться как можно реже. Он возвращает значение статуса. Если это значение равно константе CURLM_CALL_MULTI_PERFORM, это означает, что еще предстоит выполнить неотложную работу (например, отправить информацию заголовка http, соответствующую URL-адресу). То есть нам нужно продолжать вызывать эту функцию до тех пор, пока возвращаемое значение не изменится.
Следующий цикл while будет продолжаться только в том случае, если переменная $active имеет значение true. Эта переменная ранее была передана в функцию curl_multi_exec() в качестве второго параметра и показывает, есть ли еще активные соединения в дескрипторе пакета. Затем мы вызываем функцию curl_multi_select(), которая «блокируется» до тех пор, пока не произойдет активное соединение (например, получение ответа сервера). После успешного выполнения этой функции мы войдем в еще один цикл do- while и перейдем к следующему URL-адресу.
Давайте посмотрим, как применить эту функцию на практике:
Проверка подключения WordPress. Представьте, что у вас есть блог с большим количеством статей, содержащих большое количество ссылок на внешние веб-сайты. Через некоторое время значительная часть этих ссылок по тем или иным причинам стала недействительной. Либо его гармонизировали, либо весь сайт взломали...
Давайте создадим скрипт ниже, чтобы проанализировать все эти ссылки, найти веб-сайты/веб-страницы, которые не открываются или имеют ошибку 404, и создать отчет.
Обратите внимание, что нижеследующее не является настоящим работающим плагином WordPress, это всего лишь скрипт с независимыми функциями, предназначенный только для демонстрации, спасибо.
Хорошо, давайте начнем. Сначала прочитайте все эти ссылки из базы данных:
//КОНФИГ
$db_host = 'локальный хост';
$db_user = 'корень';
$db_pass = '';
$db_name = 'WordPress';
$excluded_domains = массив(
'localhost', 'www.mydomain.com');
$max_connections = 10;
//Инициализируем некоторые переменные
$url_list = массив();
$working_urls = массив();
$dead_urls = массив();
$not_found_urls = массив();
$актив = ноль;
// Подключаемся к MySQL
if (!mysql_connect($db_host, $db_user, $db_pass)) {
die('Не удалось подключиться:' . mysql_error());
}
если (!mysql_select_db($db_name)) {
die('Не удалось выбрать базу данных:' . mysql_error());
}
// Найти все статьи со ссылками
$q = "ВЫБРАТЬ post_content ИЗ wp_posts
ГДЕ post_content НРАВИТСЯ '%href=%'
И post_status = 'опубликовать'
И post_type = 'пост'";
$r = mysql_query($q) или die(mysql_error());
в то время как ($d = mysql_fetch_assoc($r)) {
// Используйте обычные совпадающие ссылки
if (preg_match_all("!href="(.*?)"!", $d['post_content'], $matches)) {
foreach ($matches[1] как $url) {
// исключаем некоторые домены
$tmp = parse_url($url);
if (in_array($tmp['host'], $excluded_domains)) {
продолжать;
}
// сохраняем URL
$url_list []= $url;
}
}
}
// Удаляем повторяющиеся ссылки
$url_list = array_values(array_unique($url_list));
если (!$url_list) {
die('Нет URL для проверки');
}Сначала мы настраиваем базу данных, серию исключаемых доменных имен ($excluded_domains) и максимальное количество одновременных подключений ($max_connections). Затем подключитесь к базе данных, получите статьи и включенные ссылки и соберите их в массив ($url_list).
Код ниже немного сложен, поэтому я объясню его подробно шаг за шагом:
// 1. Пакетный процессор
$mh = curl_multi_init();
// 2. Добавьте URL-адреса, которые необходимо обрабатывать пакетно.
for ($i = 0; $i < $max_connections; $i++) {
add_url_to_multi_handle($mh, $url_list);
}
// 3. Первоначальная обработка
делать {
$mrc = curl_multi_exec($mh, $active);
} Пока ($mrc == CURLM_CALL_MULTI_PERFORM);
// 4. Основной цикл
while ($active && $mrc == CURLM_OK) {
// 5. Есть активное соединение
if (curl_multi_select($mh) != -1) {
// 6. Работа
делать {
$mrc = curl_multi_exec($mh, $active);
} Пока ($mrc == CURLM_CALL_MULTI_PERFORM);
// 7. Есть ли у вас какая-либо информация?
если ($mhinfo = curl_multi_info_read($mh)) {
//Означает, что соединение завершилось нормально
// 8. Получить информацию из дескриптора завитка
$chinfo = curl_getinfo($mhinfo['handle']);
// 9. Мертвая ссылка?
if (!$chinfo['http_code']) {
$dead_urls []= $chinfo['url'];
// 10. 404?
} else if ($chinfo['http_code'] == 404) {
$not_found_urls []= $chinfo['url'];
// 11. Еще доступно
} еще {
$working_urls []= $chinfo['url'];
}
// 12. Удалить дескриптор
Curl_multi_remove_handle($mh, $mhinfo['handle']);
Curl_close($mhinfo['handle']);
// 13. Добавляем новый URL и делаем работу
если (add_url_to_multi_handle($mh, $url_list)) {
делать {
$mrc = curl_multi_exec($mh, $active);
} Пока ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
}
}
// 14. Закончено
Curl_multi_close ($ мх);
echo "==Мертвые URL-адреса==n";
echo implode("n",$dead_urls) "nn";
echo "==404 URL==n";
echo implode("n",$not_found_urls) "nn";
echo "==Рабочие URL==n";
echo implode("n",$working_urls);
// 15. Добавляем URL в пакетный процессор
функция add_url_to_multi_handle($mh, $url_list) {
статический $index = 0;
// Если URL остался, он бесполезен
если ($url_list[$index]) {
//Создаем новый дескриптор скручивания
$ch = Curl_init();
//Настраиваем URL
Curl_setopt($ch, CURLOPT_URL, $url_list[$index]);
// Не хочу выводить возвращенное содержимое
Curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, 1);
// Мы пойдем туда, куда нас приведет перенаправление
Curl_setopt ($ ch, CURLOPT_FOLLOWLOCATION, 1);
// Тело контента не требуется, что может сэкономить полосу пропускания и время
curl_setopt($ch, CURLOPT_NOBODY, 1);
//Добавить в пакетный процессор
curl_multi_add_handle($mh, $ch);
// Наберите счетчик, и вы сможете добавить следующий URL-адрес при следующем вызове этой функции.
$индекс++;
вернуть истину;
} еще {
// Никаких новых URL-адресов обрабатывать не нужно
вернуть ложь;
}
}Приведенный выше код объясняется ниже. Серийные номера в списке соответствуют последовательным номерам в комментариях к коду.
Создайте новый пакетный процессор. Создал мульти-дескриптор.
Позже мы создадим функцию add_url_to_multi_handle(), которая добавляет URL-адреса в пакетный обработчик. При каждом вызове этой функции в пакетный процессор добавляется новый URL-адрес. Изначально мы добавляем в пакетный процессор 10 URL-адресов (это количество определяется $max_connections).
Необходимо запустить cur_multi_exec() для выполнения работы по инициализации, пока он возвращает CURLM_CALL_MULTI_PERFORM, еще есть что сделать. Это делается в первую очередь для создания соединения, а не ожидания полного ответа URL.
Основной цикл продолжается до тех пор, пока в пакете есть активные соединения.
Curl_multi_select() ждет, пока запрос URL не приведет к активному соединению.
Работа cURL снова здесь, в основном для получения данных ответа.
Проверьте различную информацию. Когда запрос URL завершен, возвращается массив.
В возвращаемом массиве есть дескриптор cURL. Мы используем его для получения соответствующей информации для одного запроса cURL.
Если это неработающая ссылка или время запроса истекло, код состояния http не будет возвращен.
Если эту страницу невозможно найти, будет возвращен код состояния 404.
В остальных случаях мы предполагаем, что эта ссылка доступна (можно, конечно, проверить и на 500 ошибок и тому подобное...).
Удалите этот дескриптор cURL из пакета, поскольку он больше не используется, закройте его!
Отлично, теперь вы можете добавить еще один URL. И снова работа по инициализации начинается снова...
Что ж, все, что нужно было сделать, сделано. Закройте пакетный процессор и создайте отчет.
Давайте вернемся к функции, которая добавляет новый URL-адрес в пакетный процессор. Каждый раз, когда вызывается эта функция, статическая переменная $index увеличивается, чтобы мы могли знать, сколько URL-адресов осталось обработать.
Я запустил этот скрипт в своем блоге (необходимо для тестирования, некоторые неправильные ссылки были добавлены намеренно), и результаты следующие:
Всего было проверено около 40 URL-адресов, и это заняло менее двух секунд. Когда вам нужно проверить большее количество URL-адресов, можно себе представить эффект экономии! Если открыть 10 соединений одновременно, это будет в 10 раз быстрее! Кроме того, вы также можете воспользоваться функцией неблокировки пакетной обработки cURL для обработки большого количества URL-запросов без блокировки ваших веб-скриптов.
Некоторые другие полезные параметры cURL
HTTP-аутентификация. Если URL-запрос требует HTTP-аутентификации, вы можете использовать следующий код:
$url = " http://www.somesite.com/members/ ";
$ch = Curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
Curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, 1);
//Отправляем имя пользователя и пароль
Curl_setopt($ch, CURLOPT_USERPWD, "моеимя пользователя:мойпароль");
// Вы можете разрешить перенаправление
Curl_setopt ($ ch, CURLOPT_FOLLOWLOCATION, 1);
// Следующие параметры позволяют cURL
// Также можно отправить имя пользователя и пароль
Curl_setopt ($ ch, CURLOPT_UNRESTRICTED_AUTH, 1);
$output = curl_exec($ch);
Curl_close($ch);Загрузка по FTP
PHP поставляется со своей собственной библиотекой FTP, но вы также можете использовать cURL:
//Открываем указатель файла
$file = fopen("/путь/к/файлу", "r");
// URL содержит большую часть необходимой информации
$url = " ftp://имя пользователя:пароль@mydomain.com:21/путь/к/новому/файлу ";
$ch = Curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
Curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, 1);
//Загрузить связанные параметры
Curl_setopt ($ ch, CURLOPT_UPLOAD, 1);
Curl_setopt ($ ch, CURLOPT_INFILE, $ fp);
Curl_setopt($ch, CURLOPT_INFILESIZE, размер файла("/путь/к/файлу"));
// Включить ли режим ASCII (полезно при загрузке текстовых файлов)
Curl_setopt ($ ch, CURLOPT_FTPASCII, 1);
$output = curl_exec($ch);
Curl_close($ch); Чтобы обойти стену, вы можете использовать прокси-сервер для инициации запроса cURL:
$ch = Curl_init();
Curl_setopt($ch, CURLOPT_URL,'http://www.example.com');
Curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, 1);
//Указываем адрес прокси
curl_setopt($ch, CURLOPT_PROXY, '11.11.11.11:8080');
// Укажите имя пользователя и пароль, если требуется
Curl_setopt($ch, CURLOPT_PROXYUSERPWD,'пользователь:пароль');
$output = curl_exec($ch);
Curl_close ($ch); Функция обратного вызова позволяет cURL вызывать указанную функцию обратного вызова во время запроса URL. Например, начните использовать данные сразу после загрузки контента или ответа, а не дожидайтесь их полной загрузки.
$ch = Curl_init();
curl_setopt($ch, CURLOPT_URL,'http://net.tutsplus.com');
curl_setopt($ch, CURLOPT_WRITEFUNCTION, "progress_function");
Curl_exec ($ ч);
локон_закрыть ($ ч);
функция Progress_function($ch,$str) {
эхо $стр;
вернуть стрлен ($ стр);
}Эта функция обратного вызова должна возвращать длину строки, иначе эта функция не будет работать должным образом.
В процессе приема ответа URL-адреса эта функция будет вызываться до тех пор, пока будет получен пакет данных.
Резюме Сегодня мы узнали о мощных функциях и гибкой масштабируемости библиотеки cURL. Надеюсь, вам понравится. В следующий раз, когда вы захотите сделать запрос URL-адреса, рассмотрите вариант cURL!
Спасибо!
Исходный текст: Быстрый старт с cURL на основе PHP
Оригинальный текст на английском языке: http://net.tutsplus.com/tutorials/php/techniques-and-resources-for-mastering-curl/
Автор оригинала: Бурак Гузель
Источник необходимо сохранить для переиздания.