Получение HTML по HTTP в языке PHP: обзор инструментов

Раздел: Веб-программирование PHP -> HTTP клиенты

Получение 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/guzzle
use 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 отключён из соображений безопасности или из-за ограничений хостинга.

получить HTML через HTTP запрос в PHP - comments

En
Php request html (php)