Получение HTML по HTTP в языке PHP: обзор инструментов
Получение HTML через HTTP запрос в PHP: обзор способов
Основное решение: использование cURL
cURL предоставляет полный контроль над HTTP запросами и поддерживает множество опций: таймауты, SSL, редиректы, пользовательские заголовки и куки. Это наиболее эффективное решение для большинства задач.
$ch = curl_init('https://example.com');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true
]);
$html = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Ошибка: ' . curl_error($ch);
}
curl_close($ch);Php request html (получить html через http запрос в php)
Пояснение: curl_init создаёт сессию, curl_setopt_array задаёт опции. CURLOPT_RETURNTRANSFER возвращает результат, CURLOPT_FOLLOWLOCATION автоматически следует редиректам. Проверка ошибок через curl_errno и curl_error обязательна.
Типичные проблемы:
- Ошибка SSL: при самоподписанных сертификатах можно отключить проверку через CURLOPT_SSL_VERIFYPEER = false, но это снижает безопасность.
- Таймауты: увеличение CURLOPT_TIMEOUT помогает при медленных серверах.
- Проблемы с редиректами: если CURLOPT_FOLLOWLOCATION не работает из-за ограничений open_basedir, следует реализовать ручное следование.
Как получить HTML простым способом без внешних библиотек?
Функция file_get_contents с контекстом потока позволяет выполнить GET запрос минимальным кодом:
$opts = [
'http' => [
'method' => 'GET',
'header' => "User-Agent: Mozilla/5.0\r\n"
]
];
$context = stream_context_create($opts);
$html = file_get_contents('https://example.com', false, $context);
if ($html === false) {
// обработать ошибку
}Проблемы: требуется директива allow_url_fopen = On в php.ini. Нет встроенной поддержки редиректов, cookies и детальной обработки ошибок. Подходит только для простых сценариев.
Как использовать современный HTTP клиент с поддержкой PSR-7?
Библиотека Guzzle предоставляет объектно-ориентированный интерфейс, поддержку middleware, асинхронных запросов и пулов:
composer require guzzlehttp/guzzleuse GuzzleHttp\Client;
$client = new Client();
$response = $client->request('GET', 'https://example.com');
$html = $response->getBody()->getContents();Требуется Composer и автозагрузчик. Guzzle идеален для сложных проектов, но добавляет зависимость.
Как отправить запрос с пользовательскими заголовками и куками?
cURL предоставляет полный контроль над заголовками через CURLOPT_HTTPHEADER и куками через CURLOPT_COOKIE или файлы cookie:
$ch = curl_init('https://example.com');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer token123',
'Accept: application/json'
],
CURLOPT_COOKIE => 'session=abc123; user=test'
]);
$html = curl_exec($ch);
curl_close($ch);Важно корректно экранировать значения кук и заголовков. При использовании файлов cookie нужно обеспечить права на запись.
Как правильно обрабатывать ошибки HTTP запросов?
Необходимо проверять не только код возврата cURL, но и HTTP статус ответа. Пример обработки с cURL:
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode >= 400) {
// логировать ошибку, возможно повторить запрос
}Иногда сервер возвращает тело ошибки при 4xx/5xx, его тоже можно сохранить. Не следует полагаться только на curl_errno.
Пример 1. Расширенный запрос cURL с полным набором опций
$url = 'https://api.example.com/data';
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_USERAGENT => 'MyApp/1.0',
CURLOPT_HTTPHEADER => ['Accept: application/json', 'Authorization: Bearer token123'],
CURLOPT_COOKIEFILE => '/tmp/cookies.txt',
CURLOPT_COOKIEJAR => '/tmp/cookies.txt'
]);
$html = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($html === false) {
$error = curl_error($ch);
// логирование ошибки
} elseif ($httpCode >= 400) {
// обработка HTTP ошибки, возможно с записью тела $html
}
curl_close($ch);
// Результат: $html содержит тело ответа, $httpCode - код статуса (например, 200, 404).Результат при успешном запросе: $html = '...', $httpCode = 200. При ошибке 404: $html может содержать страницу ошибки, $httpCode = 404.
Пример 2. Использование file_get_contents с контекстом и получением заголовков ответа
$url = 'https://example.com';
$opts = [
'http' => [
'method' => 'GET',
'header' => "User-Agent: PHP\r\nAccept: text/html\r\n",
'ignore_errors' => true
]
];
$context = stream_context_create($opts);
$html = file_get_contents($url, false, $context);
$headers = $http_response_header;
if ($html !== false) {
// Первый заголовок обычно HTTP/1.1 200 OK
echo $headers[0];
}
// Результат: $headers[0] = 'HTTP/1.1 200 OK', $html = содержимое страницы.Важно: массив $http_response_header заполняется только после вызова file_get_contents с контекстом.
Пример 3. Асинхронные запросы с Guzzle (на основе promise)
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
$client = new Client();
$promises = [
'site1' => $client->getAsync('https://example.com'),
'site2' => $client->getAsync('https://httpbin.org/get')
];
$results = Promise\Utils::settle($promises)->wait();
foreach ($results as $name => $result) {
if ($result['state'] === 'fulfilled') {
$html = $result['value']->getBody()->getContents();
echo "$name: OK\n";
} else {
echo "$name: failed - " . $result['reason'] . "\n";
}
}
// Результат: последовательный вывод статусов и, при успехе, содержимого тела ответа.Пример 4. Ручное следование редиректам с cURL (если CURLOPT_FOLLOWLOCATION недоступен)
function fetch_with_redirects($url, $maxRedirects = 5) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_HEADER => true
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$redirectCount = 0;
while (in_array($httpCode, [301, 302, 303, 307, 308]) && $redirectCount < $maxRedirects) {
// Извлечение Location из заголовков
preg_match('/^Location: (.+)$/im', $response, $matches);
$newUrl = trim($matches[1]);
curl_setopt($ch, CURLOPT_URL, $newUrl);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$redirectCount++;
}
curl_close($ch);
// Отделяем тело от заголовков
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$body = substr($response, $headerSize);
return ['code' => $httpCode, 'body' => $body];
}
$result = fetch_with_redirects('https://goo.gl/short');
echo $result['body'];
// Результат: финальное тело после цепочки редиректов.Этот пример демонстрирует альтернативу, когда CURLOPT_FOLLOWLOCATION отключён из соображений безопасности или из-за ограничений хостинга.