11 примеров использование команд curl в режиме реального времени
Содержание:
- Простой пример использования CURL
- 2: Сохранение загруженного файла с новым именем
- Команда Curl для Работы с Файлами
- Получение данных при помощи cURL
- Netrc
- Почему cURL?
- POST (HTTP)
- Следовать за редиректами
- User Agent
- Сложные случаи авторизации: AJAX, JQuery, JavaScript и т.п.
- Пример FTP-сессии
- Cookies
- PROGRESS METER
- Как пользоваться curl?
- Имитация браузера через запросы cURL в PHP
- Множественный cURL
Простой пример использования CURL
// Инициализация библиотеки curl if ($ch = @curl_init()) { // Устанавливаем URL запроса @curl_setopt($ch, CURLOPT_URL, 'http://server.com/'); // При значении true CURL включает в вывод заголовки @curl_setopt($ch, CURLOPT_HEADER, false); // Куда помещать результат выполнения запроса: // false - в стандартный поток вывода, // true - в виде возвращаемого значения функции curl_exec. @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Максимальное время ожидания в секундах @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); // Установим значение поля User-agent @curl_setopt($ch, CURLOPT_USERAGENT, 'PHP Bot (http://blog.yousoft.ru)'); // Выполнение запроса $data = @curl_exec($ch); // Вывести полученные данные echo $data; // Освобождение ресурса @curl_close($ch); }
2: Сохранение загруженного файла с новым именем
Предположим, у вас уже есть локальный файл с тем же именем, что и у файла, загружаемого с удаленного сервера.
Чтобы избежать перезаписи одноименного локального файла, используйте аргумент -o или –output, за которым укажите имя файла, в который вы хотите сохранить содержимое.
К примеру, чтобы загрузить удаленный файл robots.txt в локальный файл do-bots.txt, введите следующую команду:
Вы снова увидите индикатор выполнения:
Теперь используйте команду cat, чтобы отобразить содержимое файла do-bots.txt и убедиться, что это именно тот загруженный вами файл:
Вы увидите:
По умолчанию curl не поддерживает перенаправления, поэтому вы можете не получить ожидаемого результата, если файлы были перемещены. Давайте посмотрим, как можно это исправить.
Команда Curl для Работы с Файлами
Команды Curl могут загружать файлы из удалённой локации. Есть два способа это сделать:
- -O сохранит файл в текущем рабочем каталоге с тем же именем, что и у удалённого;
- -o позволяет указать другое имя файла или местоположение.
Вот пример:
curl -O http://testdomain.com/testfile.tar.gz
Приведённая выше команда сохранит файл как testfile.tar.gz.
curl -o newtestfile.tar.gz http://testdomain.com/testfile.tar.gz
А эта команда сохранит его как newtestfile.tar.gz.
Если по какой-либо причине загрузка будет прервана, вы можете возобновить её с помощью следующей команды:
curl -C - -O http://testdomain.com/testfile.tar.gz
Curl также позволяет загрузить несколько файлов одновременно. Пример:
curl -O http://testdomain.com/testfile.tar.gz -O http://mydomain.com/myfile.tar.gz
Если вы хотите загрузить несколько файлов с нескольких URL, перечислите их все в файле. Команды Curl могут быть объединены с xargs для загрузки различных URL-адресов.
Например, если у нас есть файл allUrls.txt, который содержит список всех URL-адресов для загрузки, то приведённый ниже пример выполнит загрузку всех файлов с этих URL.
xargs –n 1 curl -O < allUrls.txt
Получение данных при помощи cURL
Получение данных при помощи cURL в PHP
Пример на PHP:
<?php $target_url = "http://mi-al.ru"; $ch = curl_init($target_url); curl_exec($ch); curl_close($ch); ?>
Всё очень просто:
$target_url — адрес сайта, который нас интересует. После адреса сайта можно поставить двоеточие и добавить адрес порта (если порт отличается от стандартного).
curl_init — инициализирует новый сеанс и возвращает дискриптор, который в нашем примере присваивается переменной $ch.
Затем мы выполняем запрос cURL функцией curl_exec, которой в качестве параметра передаётся дискриптор.
Всё очень логично, но при выполнении этого скрипта, на нашей странице отобразиться содержимое сайта. А что если мы не хотим отображать содержимое, а хотим записать его в переменную (для последующей обработки или парсинга).
Чуть дополним наш скрипт:
<?php $target_url = "http://mi-al.ru"; $ch = curl_init($target_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $response_data = curl_exec($ch); echo $response_data; if (curl_errno($ch) > 0) { echo 'Ошибка curl: ' . curl_error($ch); } curl_close($ch); ?>
У нас появилась строчка curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);.
curl_setopt — задаёт опции. Полный список опций можно найти на этой странице: http://php.net/manual/ru/function.curl-setopt.php
$response_data = curl_exec($ch);
Теперь значение скрипта присваивается переменной $response_data, с которой можно проводить дальнейшие операции. Например, можно вывести её содержимое.
Строчки
if (curl_errno($ch) > 0) { echo 'Ошибка curl: ' . curl_error($ch); }
служат для отладки, на случай возникновения ошибок.
Получение данных при помощи cURL в командной строке
В командной строке достаточно набрать
curl mi-al.ru
где вместо mi-al.ru — адрес вашего сайта.
Если нужно скопировать данные в переменную, а не выводить полученный результат на экран, то делаем так:
temp=`curl mi-al.ru`
При этом всё равно выводятся некие данные:
Чтобы они не выводились, добавляем ключ -s:
temp=`curl -s mi-al.ru`
Можно посмотреть, что записалось:
echo $temp | less
Netrc
Unix introduced the concept a long time ago. It is a way for a user to specify name and password for commonly visited FTP sites in a file so that you don’t have to type them in each time you visit those sites. You realize this is a big security risk if someone else gets hold of your passwords, so therefore most unix programs won’t read this file unless it is only readable by yourself (curl doesn’t care though).
Curl supports files if told to (using the / and options). This is not restricted to just FTP, so curl can use it for all protocols where authentication is used.
A very simple file could look something like:
Почему cURL?
На самом деле, существует немало альтернативных способов выборки содержания веб-страницы. Во многих случаях, главным образом из-за лени, я использовал простые PHP функции вместо cURL:
$content = file_get_contents("http://www.nettuts.com"); // или $lines = file("http://www.nettuts.com"); // или readfile("http://www.nettuts.com");
Однако данные функции не имеют фактически никакой гибкости и содержат огромное количество недостатков в том, что касается обработки ошибок и т.д. Кроме того, существуют определенные задачи, которые вы просто не можете решить благодаря этим стандартным функциям: взаимодействие с cookie, аутентификация, отправка формы, загрузка файлов и т.д.
cURL — это мощная библиотека, которая поддерживает множество различных протоколов, опций и обеспечивает подробную информацию о URL запросах.
POST (HTTP)
It’s easy to post data using curl. This is done using the option. The post data must be urlencoded.
Post a simple «name» and «phone» guestbook.
How to post a form with curl, lesson #1:
Dig out all the tags in the form that you want to fill in.
If there’s a «normal» post, you use to post. takes a full «post string», which is in the format
The ‘variable’ names are the names set with in the tags, and the data is the contents you want to fill in for the inputs. The data must be properly URL encoded. That means you replace space with + and that you replace weird letters with %XX where XX is the hexadecimal representation of the letter’s ASCII code.
Example:
(page located at )
We want to enter user ‘foobar’ with password ‘12345’.
To post to this, you enter a curl command line like:
While uses the application/x-www-form-urlencoded mime-type, generally understood by CGI’s and similar, curl also supports the more capable multipart/form-data type. This latter type supports things like file upload.
accepts parameters like . If you want the contents to be read from a file, use as contents. When specifying a file, you can also specify the file content type by appending to the file name. You can also post the contents of several files in one field. For example, the field name ‘coolfiles’ is used to send three files, with different content types using the following syntax:
If the content-type is not specified, curl will try to guess from the file extension (it only knows a few), or use the previously specified type (from an earlier file if several files are specified in a list) or else it will use the default type ‘application/octet-stream’.
Emulate a fill-in form with . Let’s say you fill in three fields in a form. One field is a file name which to post, one field is your name and one field is a file description. We want to post the file we have written named «cooltext.txt». To let curl do the posting of this data instead of your favourite browser, you have to read the HTML source of the form page and find the names of the input fields. In our example, the input field names are ‘file’, ‘yourname’ and ‘filedescription’.
To send two files in one post you can do it in two ways:
Send multiple files in a single «field» with a single field name:
Send two fields with two field names
To send a field value literally without interpreting a leading or , or an embedded , use instead of . This is recommended when the value is obtained from a user or some other unpredictable source. Under these circumstances, using instead of could allow a user to trick curl into uploading a file.
Следовать за редиректами
Сервер Google сообщил нам, что страница перемещена (301 Moved Permanently), и теперь надо запрашивать страницу . С помощью опции укажем CURL следовать редиректам:
> curl -L google.com <!doctype html> <html itemscope="" itemtype="http://schema.org/WebPage" lang="ru"> <head> <meta content="Поиск информации в интернете: веб страницы, картинки, видео и многое другое." name="description"> <meta content="noodp" name="robots"> <meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"> <meta content="origin" name="referrer"> <title>Google</title> ..........
User Agent
An HTTP request has the option to include information about the browser that generated the request. Curl allows it to be specified on the command line. It is especially useful to fool or trick stupid servers or CGI scripts that only accept certain browsers.
Example:
Other common strings:
- — Netscape Version 3 for Windows 95
- — Netscape Version 3 for Windows 95
- — Netscape Version 2 for OS/2
- — Netscape for AIX
- — Netscape for Linux
Note that Internet Explorer tries hard to be compatible in every way:
Mozilla/4.0 (compatible; MSIE 4.01; Windows 95) — MSIE for W95
Mozilla is not the only possible User-Agent name:
- — KDE File Manager desktop client
- — Lynx command line browser
Сложные случаи авторизации: AJAX, JQuery, JavaScript и т.п.
Данные заголовок правильнее было бы написать так: «Сложные» случаи авторизации. Т.е. слово «сложные» взять в кавычки. Сложными они видятся только на первый взгляд, когда непонятно: куда происходит отправка, какие имена полей, что именно отправляется и т. д.
Но, на самом деле, все они сводятся к методам POST или GET. Чтобы понять, что именно отправляется, можно сохранить страницу с формой себе на диск и на кнопку отправки повесить функцию показа сформированных для отправки данных. Или ещё проще — как я, Wireshark’ом.
Если данные правильные, а аутентификация не происходит, то нужно копать в следующих направлениях:
- задать верную строку реферера
- задать «правильную» строку пользовательского агента.
Всё это можно сделать базовыми методами cURL, но я не буду на этом останавливаться. Урок получился и без того большим, а ведь я ещё хотел показать пару трюков с cURL.
Пример FTP-сессии
$fp = fopen(__FILE__, "r"); $url = "ftp://username:password@mydomain.com:21/path/to/newfile.php"; $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_FTPASCII, 1); curl_setopt($ch, CURLOPT_INFILESIZE, filesize(__FILE__)); $result = curl_exec($ch); curl_close($ch);
При возникновении проблем в использование cURL необходимо добавить следующие строки перед вызовом curl_close для получения отчета о последнем выполненном запросе:
print_r(curl_getinfo($ch)); echo "cURL error number:".curl_errno($ch)." "; echo "cURL error:".curl_error($ch)." "; curl_close($ch);
3707
Веб разработка
Cookies
С помощью cookies веб-браузеры контролируют состояние на стороне
клиента. Cookie — это имя с присоединенным содержимым. Сервер при
помощи отправки cookies сообщает клиенту путь и имя хоста, по
которому в следующий раз должны быть отправлены cookies, сообщает
время жизни cookies и некоторые другие параметры.
Когда клиент соединяется с сервером по адресу, указанному в
принятом cookie, клиент посылает этот cookie к серверу (если время
жизни не истекло).
Многие приложения и сервера используют этот метод, чтобы
объединить нескольких запросов в одну логическую сессию. Чтобы curl
также мог выполнять такую функцию, мы должны уметь сохранять и
отправлять cookies, как и делают браузеры.
Простейший способ отправить cookie к серверу при получении
страницы с помощью curl, это добавить соответствующий ключ в
командной строке:
# curl -b "name=Daniel" www.cookiesite.com
Cookies отправляются как обычные HTTP-заголовки. Это позволяет curl
сохранять cookies, сохраняя заголовки. Сохранение cookies с помощью
curl выполняется командой:
# curl -D headers_and_cookies www.cookiesite.com
(кстати, для сохранения cookies лучше использовать ключ -c, об этом
ниже).
У curl имеется полнофункциональный обработчик cookies, который
полезен, когда вы хотите соединиться в очередной раз к серверу и
использовать cookies, сохраненные в прошлый раз (либо подработанные
вручную). Для использования cookies, сохраненных в файле, вызовите
curl так:
# curl -b stored_cookies_in_file www.cookiesite.com
«Cookie-движок» curl включается, когда вы указываете ключ
-b. Если вы хотите, чтобы curl лишь воспринимал cookies, используйте
-b с указанием файла, которого не существует. Например, если вы
хотите, чтобы curl принял cookies со страницы, а затем пошел по
перенаправлению (возможно, отдав принятый только что cookie), то
можно вызывать curl так:
# curl -b nada -L www.cookiesite.com
Curl умеет читать и писать cookie-файлы, имеющие формат Netscape и
Mozilla. Это удобный способ обмениваться cookies между браузерами и
автоматическими скриптами. Ключ -b автоматически определяет, является
ли данный файл cookie-файлом указанных браузеров и обрабатывает его
соответствующим образом, а используя ключ -c/—cookie-jar, вы можете
заставить curl записать новый cookie-файл по завершении операции:
# curl -b cookies.txt -c newcookies.txt www.cookiesite.com
PROGRESS METER
curl normally displays a progress meter during operations, indicating the amount of transferred data, transfer speeds and estimated time left, etc. The progress meter displays number of bytes and the speeds are in bytes per second. The suffixes (k, M, G, T, P) are 1024 based. For example 1k is 1024 bytes. 1M is 1048576 bytes.
curl displays this data to the terminal by default, so if you invoke curl to do an operation and it is about to write data to the terminal, it disables the progress meter as otherwise it would mess up the output mixing progress meter and response data.
If you want a progress meter for HTTP POST or PUT requests, you need to redirect the response output to a file, using shell redirect (>), or similar.
It is not the same case for FTP upload as that operation does not spit out any response data to the terminal.
If you prefer a progress «bar» instead of the regular meter, -#, —progress-bar is your friend. You can also disable the progress meter completely with the option.
Как пользоваться curl?
Мы рассмотрели все, что касается теории работы с утилитой curl, теперь пришло время перейти к практике, и рассмотреть примеры команды curl.
Загрузка файлов
Самая частая задача — это загрузка файлов linux. Скачать файл очень просто. Для этого достаточно передать утилите в параметрах имя файла или html страницы:
curl https://raw.githubusercontent.com/curl/curl/master/README.md
Но тут вас ждет одна неожиданность, все содержимое файла будет отправлено на стандартный вывод. Чтобы записать его в какой-либо файл используйте:
curl -o readme.txt https://raw.githubusercontent.com/curl/curl/master/README.md
А если вы хотите, чтобы полученный файл назывался так же, как и файл на сервере, используйте опцию -O:
curl -O https://raw.githubusercontent.com/curl/curl/master/README.md
Если загрузка была неожиданно прервана, вы можете ее возобновить:
curl -# -C — -O https://cdn.kernel.org/pub/linux/kernel/v4.x/testing/linux-4.11-rc7.tar.xz
Если нужно, одной командой можно скачать несколько файлов:
curl -O https://raw.githubusercontent.com/curl/curl/master/README.md -O https://raw.githubusercontent.com/curl/curl/master/README
Еще одна вещь, которая может быть полезной администратору — это загрузка файла, только если он был изменен:
curl -z 21-Dec-17 https://raw.githubusercontent.com/curl/curl/master/README.md -O https://raw.githubusercontent.com/curl/curl/master/README
Данная команда скачает файл, только если он был изменен после 21 декабря 2017.
Ограничение скорости
Вы можете ограничить скорость загрузки до необходимого предела, чтобы не перегружать сеть с помощью опции -Y:
curl —limit-rate 50K -O https://cdn.kernel.org/pub/linux/kernel/v4.x/testing/linux-4.11-rc7.tar.xz
Здесь нужно указать количество килобайт в секунду, которые можно загружать. Также вы можете разорвать соединение если скорости недостаточно, для этого используйте опцию -Y:
curl -Y 100 -O https://raw.githubusercontent.com/curl/curl/master/README.md
Передача файлов
Загрузка файлов, это достаточно просто, но утилита позволяет выполнять и другие действия, например, отправку файлов на ftp сервер. Для этого существует опция -T:
curl -T login.txt ftp://speedtest.tele2.net/upload/
Или проверим отправку файла по HTTP, для этого существует специальный сервис:
curl -T ~/login.txt http://posttestserver.com/post.php
В ответе утилита сообщит где вы можете найти загруженный файл.
Отправка данных POST
Вы можете отправлять не только файлы, но и любые данные методом POST. Напомню, что этот метод используется для отправки данных различных форм. Для отправки такого запроса используйте опцию -d. Для тестирования будем пользоваться тем же сервисом:
curl -d «field1=val&fileld2=val1″http://posttestserver.com/post.php
Если вас не устраивает такой вариант отправки, вы можете сделать вид, что отправили форму. Для этого есть опция -F:
curl -F «password=@pass;type=text/plain» http://posttestserver.com/post.php
Здесь мы передаем формой поле password, с типом обычный текст, точно так же вы можете передать несколько параметров.
Передача и прием куки
Куки или Cookie используются сайтами для хранения некой информации на стороне пользователя. Это может быть необходимо, например, для аутентификации. Вы можете принимать и передавать Cookie с помощью curl. Чтобы сохранить полученные Cookie в файл используйте опцию -c:
curl -c cookie.txt http://posttestserver.com/post.php
Затем можно отправить cookie curl обратно:
curl -b cookie.txt http://posttestserver.com/post.php
Передача и анализ заголовков
Не всегда нам обязательно нужно содержимое страницы. Иногда могут быть интересны только заголовки. Чтобы вывести только их есть опция -I:
curl -I https://losst.ru
А опция -H позволяет отправить нужный заголовок или несколько на сервер, например, можно передать заголовок If-Modified-Since чтобы страница возвращалась только если она была изменена:
curl -I —хедер ‘If-Modified-Since: Mon, 26 Dec 2016 18:13:12 GMT’ https://losst.ru
Аутентификация curl
Если на сервере требуется аутентификация одного из распространенных типов, например, HTTP Basic или FTP, то curl очень просто может справиться с такой задачей. Для указания данных аутентификации просто укажите их через двоеточие в опции -u:
curl -u ftpuser:ftppass -T — ftp://ftp.testserver.com/myfile_1.txt
Точно так же будет выполняться аутентификация на серверах HTTP.
Использование прокси
Если вам нужно использовать прокси сервер для загрузки файлов, то это тоже очень просто. Достаточно задать адрес прокси сервера в опции -x:
curl -x proxysever.test.com:3128 http://google.co.in
Имитация браузера через запросы cURL в PHP
Многие сайты защищаются от парсинга, отслеживая данные переменных user agent, referer, cookie. На сервере проверяются эти данные и, если подозрений на парсинг нет, то возвращается страница сайта.
Так как запросы curl в php данные этих переменных не передают, то такая защита от парсинга сайта вернет ошибку 404 или 500. Чтобы этого не происходило, можно сымитировать запрос страницы из браузера, добавив, например, следующие заголовки:
$headers = array( '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('http://yandex.ru'); curl_setopt($ch, CURLOPT_COOKIEFILE, __DIR__ . '/cookie.txt'); curl_setopt($ch, CURLOPT_COOKIEJAR, __DIR__ . '/cookie.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;
Можно посмотреть через панель для разработчиков заголовки, которые передает браузер при обращение к страницам сайтов и использовать их для запроса cURL в PHP.
Множественный cURL
Одной из самых сильных сторон cURL является возможность создания «множественных» cURL обработчиков. Это позволяет вам открывать соединение к множеству URL одновременно и асинхронно.
В классическом варианте cURL запроса выполнение скрипта приостанавливается, и происходит ожидание завершения операции URL запроса, после чего работа скрипта может продолжиться. Если вы намереваетесь взаимодействовать с целым множеством URL, это приведёт к довольно-таки значительным затратам времени, поскольку в классическом варианте вы можете работать только с одним 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); $active = null; //выполнение do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); while ($active && $mrc == CURLM_OK) { if (curl_multi_select($mh) != -1) { do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); } } //закрытие curl_multi_remove_handle($mh, $ch1); curl_multi_remove_handle($mh, $ch2); curl_multi_close($mh);
Идея состоит в том, что вы можете использовать множественные cURL обработчики. Используя простой цикл, вы можете отследить, какие запросы ещё не выполнились.
В этом примере есть два основных цикла. Первый цикл do-while вызывает функцию curl_multi_exec(). Эта функция не блокируемая. Она выполняется с той скоростью, с которой может, и возвращает состояние запроса. Пока возвращенное значение является константой ‘CURLM_CALL_MULTI_PERFORM’, это означает, что работа ещё не завершена (например, в данный момент происходит отправка http заголовков в URL); Именно поэтому мы продолжаем проверять это возвращаемое значение, пока не получим другой результат.
В следующем цикле мы проверяем условие, пока переменная $active = ‘true’. Она является вторым параметром для функции curl_multi_exec(). Значение данной переменной будет равно ‘true’, до тех пор, пока какое-то из существующих изменений является активным. Далее мы вызываем функцию curl_multi_select(). Её выполнение ‘блокируется’, пока существует хоть одно активное соединение, до тех пор, пока не будет получен ответ. Когда это произойдёт, мы возвращаемся в основной цикл, чтобы продолжить выполнение запросов.
А теперь давайте применим полученные знания на примере, который будет реально полезным для большого количества людей.