Только поиск заголовка в php через curl
На самом деле у меня есть два вопроса.
(1) Есть ли снижение мощности обработки или пропускной способности, используемой на удаленном сервере, если я получаю только заголовки, а не полный поиск страниц, используя php и curl?
(2) Поскольку я думаю, и я могу ошибаться, этот ответ на первые вопросы - ДА, я пытаюсь получить последнюю измененную дату или If-Modified-Since заголовок удаленного файла только для того, чтобы сравнить его со временем -date локально хранимых данных, поэтому я могу, если он был изменен, сохранить его локально. Тем не менее, мой script кажется неспособным получить эту часть информации, я получаю NULL
, когда я запускаю это:
class last_change {
public last_change;
function set_last_change() {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://url/file.xml");
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_FILETIME, true);
curl_setopt($curl, CURLOPT_NOBODY, true);
// $header = curl_exec($curl);
$this -> last_change = curl_getinfo($header);
curl_close($curl);
}
function get_last_change() {
return $this -> last_change['datetime']; // I have tested with Last-Modified & If-Modified-Since to no avail
}
}
В случае, если $header = curl_exec($curl)
не выполняется, отображаются данные заголовка, даже если я его не просил и выглядит следующим образом:
HTTP/1.1 200 OK
Date: Fri, 04 Sep 2009 12:15:51 GMT
Server: Apache/2.2.8 (Linux/SUSE)
Last-Modified: Thu, 03 Sep 2009 12:46:54 GMT
ETag: "198054-118c-472abc735ab80"
Accept-Ranges: bytes
Content-Length: 4492
Content-Type: text/xml
Исходя из этого, возвращается "Last-Modified".
Итак, что я делаю неправильно?
Ответы
Ответ 1
Вы передаете $header в curl_getinfo()
. Это должно быть $curl
(ручка завитка). Вы можете получить только filetime
, передав CURLINFO_FILETIME
в качестве второго параметра в curl_getinfo()
. (Часто filetime
недоступен, и в этом случае он будет отображаться как -1).
Ваш класс, кажется, расточительный, хотя и отбрасывает много информации, которая может быть полезна. Здесь можно сделать другой способ:
class URIInfo
{
public $info;
public $header;
private $url;
public function __construct($url)
{
$this->url = $url;
$this->setData();
}
public function setData()
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $this->url);
curl_setopt($curl, CURLOPT_FILETIME, true);
curl_setopt($curl, CURLOPT_NOBODY, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);
$this->header = curl_exec($curl);
$this->info = curl_getinfo($curl);
curl_close($curl);
}
public function getFiletime()
{
return $this->info['filetime'];
}
// Other functions can be added to retrieve other information.
}
$uri_info = new URIInfo('http://www.codinghorror.com/blog/');
$filetime = $uri_info->getFiletime();
if ($filetime != -1) {
echo date('Y-m-d H:i:s', $filetime);
} else {
echo 'filetime not available';
}
Да, загрузка будет легче на сервере, поскольку она возвращает только HTTP-заголовок (в ответе, в конце концов, запрос HEAD
). Сколько легче будет сильно варьироваться.
Ответ 2
Зачем использовать CURL для этого? Для этого есть PHP-функция:
$headers=get_headers("http://www.amazingjokes.com/img/2014/530c9613d29bd_CountvonCount.jpg");
print_r($headers);
возвращает следующее:
Array
(
[0] => HTTP/1.1 200 OK
[1] => Date: Tue, 11 Mar 2014 22:44:38 GMT
[2] => Server: Apache
[3] => Last-Modified: Tue, 25 Feb 2014 14:08:40 GMT
[4] => ETag: "54e35e8-8873-4f33ba00673f4"
[5] => Accept-Ranges: bytes
[6] => Content-Length: 34931
[7] => Connection: close
[8] => Content-Type: image/jpeg
)
После этого вам будет легко получить содержимое.
Вы также можете добавить формат = 1 в get_headers:
$headers=get_headers("http://www.amazingjokes.com/img/2014/530c9613d29bd_CountvonCount.jpg",1);
print_r($headers);
Это вернет следующее:
Array
(
[0] => HTTP/1.1 200 OK
[Date] => Tue, 11 Mar 2014 22:44:38 GMT
[Server] => Apache
[Last-Modified] => Tue, 25 Feb 2014 14:08:40 GMT
[ETag] => "54e35e8-8873-4f33ba00673f4"
[Accept-Ranges] => bytes
[Content-Length] => 34931
[Connection] => close
[Content-Type] => image/jpeg
)
Подробнее здесь (PHP.NET)
Ответ 3
(1) Да. Запрос HEAD (как вы выдаете в этом случае) намного легче на сервере, потому что он возвращает заголовки HTTP, а не заголовки и контент, как стандартный запрос GET.
(2) Перед вызовом curl_exec()
вам нужно установить опцию CURLOPT_RETURNTRANSFER true
, чтобы вернуть содержимое, а не напечатать:
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
Это также должно сделать ваш класс работать правильно.
Ответ 4
Вам нужно добавить
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
чтобы вернуть заголовок вместо его печати.
Вернуть ли только заголовки легче на сервере, зависит от выполняемого script, но обычно это будет.
Я думаю, вы также хотите "filetime" вместо "datetime".
Ответ 5
Вы можете установить контекст потока по умолчанию:
stream_context_set_default(
array(
'http' => array(
'method' => 'HEAD'
)
)
);
Затем используйте:
$headers = get_headers($url,1);
get_headers кажется более эффективным, чем cURL, когда get_headers пропускают такие шаги, как триггерные процедуры проверки подлинности, такие как запросы входа в систему или файлы cookie.
Ответ 6
Вот моя реализация с использованием CURLOPT_HEADER, а затем анализ выходной строки на карту:
function http_headers($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$headers = curl_exec($ch);
curl_close($ch);
$data = [];
$headers = explode(PHP_EOL, $headers);
foreach ($headers as $row) {
$parts = explode(':', $row);
if (count($parts) === 2) {
$data[trim($parts[0])] = trim($parts[1]);
}
}
return $data;
};
Использование образца:
$headers = http_headers('https://i.ytimg.com/vi_webp/g-dKXOlsf98/hqdefault.webp');
print_r($headers);
Array
(
['Content-Type'] => 'image/webp'
['ETag'] => '1453807629'
['X-Content-Type-Options'] => 'nosniff'
['Server'] => 'sffe'
['Content-Length'] => 32958
['X-XSS-Protection'] => '1; mode=block'
['Age'] => 11
['Cache-Control'] => 'public, max-age=7200'
)