Загрузка HTML страниц в PHP: способы реализации
Основные методы сохранения HTML страниц в PHP
Самый надёжный и гибкий способ - использование расширения cURL.
Библиотека cURL позволяет отправлять HTTP запросы с полным контролем параметров: заголовки, таймауты, поддержка кук, редиректы, работа через прокси. Для сохранения HTML страницы используется функция curl_exec в паре с настройками через curl_setopt. Ниже приведён базовый пример.
$url = 'https://example.com';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$html = curl_exec($ch);
if (curl_errno($ch)) {
// обработка ошибки
$error = curl_error($ch);
} else {
file_put_contents('page.html', $html);
}
curl_close($ch);
сохранение html страницы php (сохранение html-страницы с помощью php)
Шаги: инициализация дескриптора, настройка параметров, выполнение, сохранение результата в файл. Цель - получение полного HTML кода страницы с возможностью имитации браузера. Подходит для сайтов с простой структурой, не требующих выполнения JavaScript.
Как сохранить страницу без дополнительных расширений используя file_get_contents?
Если на сервере включена директива allow_url_fopen, можно применить встроенную функцию file_get_contents с контекстом потока. Это самый простой вариант, не требующий установки curl.
$options = [
'http' => [
'method' => 'GET',
'header' => "User-Agent: Mozilla/5.0\r\n"
]
];
$context = stream_context_create($options);
$html = file_get_contents('https://example.com', false, $context);
if ($html !== false) {
file_put_contents('page.html', $html);
}
Цель - быстрая загрузка небольших страниц на серверах с ограничениями на использование cURL.
Как выполнить потоковое сохранение большого HTML документа с помощью fopen?
Для очень крупных файлов, которые не умещаются в памяти, используют потоковое чтение через fopen и fread. Это экономит оперативную память.
$src = fopen('https://example.com', 'r');
$dest = fopen('page.html', 'w');
if ($src && $dest) {
while (!feof($src)) {
$chunk = fread($src, 8192);
fwrite($dest, $chunk);
}
fclose($src);
fclose($dest);
}
Цель - загрузка страниц размером от нескольких мегабайт (например, полные дампы или бинарные данные) при дефиците памяти.
Как загрузить HTML с помощью современного HTTP клиента Guzzle?
Composer пакет Guzzle предоставляет объектно ориентированный интерфейс, автоматически обрабатывает PSR-7 запросы, поддерживает пул соединений, куки, прокси, асинхронные запросы. Базовый пример для синхронной загрузки.
use GuzzleHttp\Client;
$client = new Client([
'timeout' => 30,
'allow_redirects' => true
]);
$response = $client->get('https://example.com');
$html = $response->getBody()->getContents();
file_put_contents('page.html', $html);
Цель – интеграция с современными PHP фреймворками, где уже используется Composer, а также работа с API, требующая сложных заголовков и обработки ответов.
composer require guzzlehttp/guzzle), проблемы с сертификатами SSL, конфликты версий PHP.Когда оправдано использование системной утилиты wget из PHP?
Если cURL отключён, а allow_url_fopen закрыт, можно вызвать внешнюю программу через exec или shell_exec.
exec('wget -O page.html https://example.com 2>&1', $output, $return_code);
if ($return_code === 0) {
// успешно
}
Цель – экстренное решение на серверах с жёсткими ограничениями, где доступна только консольная утилита.
Детальный пример с cURL: установка User-Agent, куки, таймаут, обработка редиректов
$url = 'https://httpbin.org/html';
$cookieFile = tempnam(sys_get_temp_dir(), 'CURLCOOKIE');
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_TIMEOUT => 20,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
CURLOPT_COOKIEJAR => $cookieFile,
CURLOPT_COOKIEFILE => $cookieFile,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_CAINFO => '/etc/ssl/certs/ca-certificates.crt'
]);
$html = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode === 200) {
file_put_contents('page_with_cookies.html', $html);
echo "Страница сохранена, код ответа: $httpCode";
} else {
echo "Ошибка HTTP: $httpCode";
}
curl_close($ch);
unlink($cookieFile);
Страница сохранена, код ответа: 200
Пояснение:
массив параметров сокращает запись. Куки сохраняются во временный файл и отправляются при редиректах. Указание пути к CA сертификатам обеспечивает проверку SSL.Потоковое сохранение с Guzzle и проверкой статуса
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
$client = new Client(['base_uri' => 'https://httpbin.org']);
try {
$response = $client->get('/html', [
'stream' => true, // возвращает поток
'timeout' => 15
]);
if ($response->getStatusCode() === 200) {
$body = $response->getBody();
$file = fopen('stream_page.html', 'w');
while (!$body->eof()) {
fwrite($file, $body->read(4096));
}
fclose($file);
echo "Файл сохранён через поток";
}
} catch (RequestException $e) {
echo "Ошибка: " . $e->getMessage();
}
Файл сохранён через поток
Использование флага 'stream' => true позволяет читать тело ответа по частям, избегая загрузки всех данных в память.
Обработка ошибок при file_get_contents и контекст HTTPS
$context = stream_context_create([
'http' => [
'method' => 'GET',
'timeout' => 10,
'header' => "Accept: text/html\r\n"
],
'ssl' => [
'verify_peer' => true,
'cafile' => '/path/to/cacert.pem'
]
]);
$html = @file_get_contents('https://self-signed.badssl.com/', false, $context);
if ($html === false) {
$error = error_get_last();
echo "Не удалось загрузить: " . $error['message'];
} else {
file_put_contents('page_ssl.html', $html);
echo "Успешно";
}
Не удалось загрузить: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
Типичная ошибка – невалидный SSL сертификат. Решение: либо указать правильный cafile, либо временно отключить проверку (не рекомендуется).
Асинхронные запросы с Guzzle для массовой загрузки страниц
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
$client = new Client(['timeout' => 30]);
$urls = [
'https://example.com',
'https://httpbin.org/html',
'https://google.com'
];
$promises = [];
foreach ($urls as $url) {
$promises[$url] = $client->getAsync($url);
}
$results = Promise\settle($promises)->wait();
foreach ($results as $url => $result) {
if ($result['state'] === 'fulfilled') {
$html = $result['value']->getBody()->getContents();
file_put_contents(basename($url) . '.html', $html);
} else {
echo "Ошибка загрузки $url: " . $result['reason'] . "\n";
}
}
(файлы example.com.html, httpbin.org.html, google.com.html созданы)
Асинхронный подход позволяет одновременно отправлять несколько запросов, экономя общее время. Используется метод getAsync и ожидание через settle.