|
|
|
| Здравствуйте!
Как прочесть http-заголовки, по заданному URL, которые выдает сервер?
К примеру:
HTTP/1.1 200 OK
Server: nginx/0.1.16
Date: Mon, 17 Oct 2005 08:16:38 GMT
Content-Type: text/html; charset=windows-1251
Connection: close
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Last-Modified: Mon, 17 Oct 2005 08:16:38 GMT | |
|
|
|
|
|
|
|
для: kran
(17.10.2005 в 14:59)
| | Это можно сделать при помощи следующего скрпта
<?php
// А это сама функция узнавания размера
function get_content($hostname, $path)
{
$line = "";
// Устанавливаем соединение, имя которого
// передано в параметре $hostname
$fp = fsockopen($hostname, 80, $errno, $errstr, 30);
// Проверяем успешность установки соединения
if (!$fp) echo "$errstr ($errno)<br />\n";
else
{
// Формируем HTTP-запрос для передачи
// его серверу
$headers = "GET $path HTTP/1.1\r\n";
$headers .= "Host: $hostname\r\n";
$headers .= "Connection: Close\r\n\r\n";
// Отправляем HTTP-запрос серверу
fwrite($fp, $headers);
$end = $false;
// Получаем ответ
while (!$end)
{
$line = fgets($fp, 1024);
if (trim($line) == "") $end = true;
else $out[] = $line;
}
fclose($fp);
}
return $out;
}
$hostname = "www.mail.ru";
$path = "/";
// Устанавливаем большее время работы
// скрипта - пока вся страница не будет загружена
// она не будет отображена
set_time_limit(180);
// Вызываем функцию
$out = get_content($hostname, $path);
// Выводим содержимое массива
foreach($out as $http)
{
echo $http."<br>";
}
?>
|
Здесь заголовки извлекаются для www.mail.ru, ответ может иметь следующий вид
HTTP/1.1 200 OK
Date: Mon, 17 Oct 2005 15:18:42 GMT
Server: Apache/1.3.31 (Unix) mod_deflate/1.0.21 rus/PL30.20
Set-Cookie: Mpopl=445694679; expires=Mon, 17 Oct 2005 15:33:42 GMT; path=/; domain=.mail.ru
Set-Cookie: mrcu=1F214353C0D209CEE256C14DD052; expires=Sun, 20 Jul 2036 07:30:17 GMT; path=/; domain=.mail.ru
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Last-Modified: Sun, 20 Jul 2036 07:30:17 GMT
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=windows-1251
Vary: user-agent
|
| |
|
|
|
|
|
|
|
для: cheops
(17.10.2005 в 19:19)
| | 1) А можно получить только определенные, интересующие заголовки, или надо все циклом перебирать?
2)Относятся ли значения title и description к заголовкам?
3)Что лучше использовать при определении кодировки страницы, значение которое возвращает сервер в заголовке или значения из мета-тега?
Как поступить в случае когда сервер не отдает заголовка с кодировкой, а в мета-теге кодировка указана, или наоборот? Пример: www.google.ru
Или вариант, когда сайт находится у хостера, где сервер при запросе отдает одну кодировку, а на сайте, в мета-теге указана другая?
P.S.: Очепятка в строке $end = $false; | |
|
|
|
|
|
|
|
для: kran
(17.10.2005 в 21:24)
| | 1) Да можно любые - это уже технический вопрос
2) Нет они к HTTP-заголовкам не относятся, к ним относятся только META-заголовки с атрибутами HTTP-EQUIV и CONTENT - это в общем и есть альтернативный способ их указания.
<meta HTTP-EQUIV="Expires" CONTENT="0">
|
3) Лучше из META-тэга, разработчику виднее в какой кодировке страница. Если есть META-заголовок с кодировкой - всегда берите от туда. | |
|
|
|
|
|
|
|
для: cheops
(17.10.2005 в 23:33)
| | 1)А если на странице нет МЕТА-заголовка указывающего кодировку, тогда кодировка берется из ответа сервера, или как?
2)К примеру сайт www.mukhin.ru Браузер его отображает правильно и мой скрипт его индексирует правильно (по умолчанию пишет w-1251, если не указана другая), а кодировка нигде не указана. Что в таком случае делать? Как проверить действительно ли кодировка такая какую я присваиваю по умолчанию, или не добавлять сайт в индекс вообще?
А вот 2 сайта www.abok.ru и www.s-h.ru, в МЕТА указана кодировка windows-1251, а сервер выдает koi8-r, причем браузер показывает нормально, а скрипту выдается все в koi8-r , и в результате в индексе крякозябры. | |
|
|
|
|
|
|
|
для: kran
(18.10.2005 в 00:15)
| | 1) Да.
2) Тут следует отталкиваться от следующего. В конфигурационном файле httpd.conf можно выставить кодировку по умолчанию. Именно такую кодировку сервер будет отправлять в HTTP-заголовке. Однако она может не совпадать с кодировкой реальных страниц, так как один разработчик будет использовать cp-1251, другой koi8-r, третий utf-8, сервер не может анализировать где какая кодировка - он шлёт то, что у него выставлено в конфиге. Разработчик с другой стороны всегда знает какая у него кодировка на странице и выставляет её правильно. Поэтому браузер в первую очередь ориентируется на META-заголовки и лишь затем на HTTP-заголовки сервера. | |
|
|
|
|
|
|
|
для: cheops
(18.10.2005 в 13:50)
| | А вот эти 2 сайта www.abok.ru и www.s-h.ru (на самом деле их сотни), кодировка указана в МЕТА windows-1251. С этой кодировкой я их и обрабатываю, а на самом деле информация возвращается кодированная в koi8-r, и я ничего немогу с этим сделать!
Т.е. если бы значение кодировки возвращалось другое, отличное от windows-1251, тогда я бы конвертировал данные в нужную мне кодировку на основании полученной. Если бы значения кодировки не были получены, тогда сайт бы не добавлялся в индекс.
Но здесь другое дело, я получаю данные о кодировке windows-1251(значит кодировка есть и сайт в индекс добавляется, и конвертировать никуда не надо, так как индекс я записываю с этой кодировкой, а значит оставляю все как есть), а данные идут с кодировкой koi8-r, забивая весь индекс абракадаброй! А если учесть, что такая фигня с каждым 10 сайтом, то это зараза сводит на нет всю работу!
Что с этой гадостью можно сделать?
Помогите ;-)) | |
|
|
|
|
|
|
|
для: kran
(18.10.2005 в 15:31)
| | Хм... загрузил www.abok.ru и ww.s-h.ru - указано windows-1251 и текст в windows-1251... Вы каким кодом загружаете страницу? | |
|
|
|
|
|
|
|
для: cheops
(18.10.2005 в 20:54)
| | В том-то и дело что через браузер отображается все нормально, а когда я захожу на эти страницы скриптом, то вылазит бяка!
Код примерно такой:
<?php
set_time_limit(600);
$url="http://www.abok.ru";
$text=file_get_contents($url);
$text=str_replace("\n"," ", $text);
$text=str_replace("\r","", $text);
$text=str_replace('"',"", $text);
$text=str_replace("'","", $text);
preg_match("#<title>([^<]+)</title>#iU", $text, $t);
$title=trim($t[1]);
preg_match("#<meta[\s]+name[\s]*=[\s]*description[\s]*content[\s]*=([^>]+)>#iU", $text, $d);
$description=trim($d[1]);
echo "<b>Название:</b> $title <br>\n";
echo "<b>Описание:</b> $description <br>\n";
echo "<b>URL:</b><a href=$url target=_blank>$url</a>\n";
?>
|
можно еще попробовать с www.stroyportal.ru или www.vashdom.ru - там все получается как надо! | |
|
|
|
|
|
|
|
для: kran
(19.10.2005 в 12:23)
| | Хм... похоже он реагирует на USER_AGENT сервера, в котором обычно пишется PHP - можно попробовать подделать пользовательский агент, но тогда необходимо переходить на сокеты. | |
|
|
|
|
|
|
|
для: cheops
(19.10.2005 в 14:31)
| | Из ваших слов понял, что еще не все потеряно? ;-))
Только что конкретно надо делать непонял :((
А вы не могли бы превести пример!
З.Ы.: Сегодня в Ozon.ru купил вашу книгу, та которая самая толстая и с CD! :-))
Буду ждать когда придет, очень надеюсь что поможет! | |
|
|
|
|
|
|
|
для: kran
(19.10.2005 в 16:34)
| | Пример работы с сокетами приведён в теме по ссылке http://www.softtime.ru/forum/read.php?id_forum=1&id_theme=5045, для подделки USER_AGENT вам потребуется добавить в блок
<?php
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: $st\r\n";
$out .= "Connection: Close\r\n\r\n";
?>
|
ещё один заголовок
<?php
$out = "GET / HTTP/1.1\r\n";
$out .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1\r\n";
$out .= "Host: $st\r\n";
$out .= "Connection: Close\r\n\r\n";
?>
|
PS Вообще в PHP 5. Практика создания Web-сайтов сокеты не рассматриваются - там рассмотрены мирные, но большие Web-приложения. Сокеты достаточно подробно рассматриваются в "PHP 5. на примерах". А разнообразная подделка пользовательских данных, cookie, реферерры, пользовательские агенты, а также методы противостояния такой подделке со стороны посетителей будет подробно рассмотрена в ответах на задания нашей шестой книги "PHP-головоломки для хакера", работа над которой сейчас ведётся. | |
|
|
|
|
|
|
|
для: kran
(17.10.2005 в 14:59)
| | Че то ничего не понимаю!
Похоже я уже туплю и что-то делаю не так :((
<?php
set_time_limit(600);
$url="www.abok.ru";
$fp = fsockopen($url, 80, $errno, $errstr, 30);
if (!$fp) { echo "$errstr($errno)<br>\n"; }
else
{
$out = "GET / HTTP/1.1\r\n";
$out .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1\r\n";
$out .= "Host: $url\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
$text = fgets($fp, 3000);
fclose($fp);
}
preg_match("#<title>([^<]+)</title>#iU", $text, $t);
$title=trim($t[1]);
preg_match("#<meta[\s]+name[\s]*=[\s]*description[\s]*content[\s]*=([^>]+)>#iU", $text, $d);
$description=trim($d[1]);
echo "<b>TITLE:</b> $title <br>\n";
echo "<b>DESCRIPTION:</b> $description <br>\n";
echo "<b>URL:</b><a href=$url target=_blank>$url</a>\n";
?>
|
| |
|
|
|
|
|
|
|
для: kran
(19.10.2005 в 21:54)
| | Нет, от цикла здесь избавиться нельзя
<?php
set_time_limit(600);
$url="www.abok.ru";
$fp = fsockopen($url, 80, $errno, $errstr, 30);
$text = "";
if (!$fp)
{
echo "$errstr($errno)<br>\n";
}
else
{
$out = "GET / HTTP/1.1\r\n";
$out .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1\r\n";
$out .= "Host: $url\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp))
{
$text .= fgets($fp, 3000);
}
fclose($fp);
}
preg_match("#<title>([^<]+)</title>#iU", $text, $t);
$title=trim($t[1]);
preg_match("#<meta[\s]+name[\s]*=[\s]*description[\s]*content[\s]*=([^>]+)>#iU", $text, $d);
$description=trim($d[1]);
echo "<b>TITLE:</b> $title <br>\n";
echo "<b>DESCRIPTION:</b> $description <br>\n";
echo "<b>URL:</b><a href=$url target=_blank>$url</a>\n";
?>
|
PS Слушайте, а ведь действительно меняют кодировку в зависимости от пользовательского агента :))) дур дом, они на какое место в поисковых системах расчитывают... | |
|
|
|
|
|
|
|
для: cheops
(20.10.2005 в 00:33)
| | Все супер! Работает отлично, но нашел еще пару проблем!
1) При запросе определенных сайтов, сервер возвращает код 301 или 302, адрес редиректа посылается сервером в заголовке "Location". Т.е. все что нужно сделать это написать условие: если есть код редиректа, то брать url из заголовка Location. Вопрос можно ли выцепить нужный мне заголовок, или нужно перебирать весь массив который выдает сервер?
Я этот вопрос уже задавал и вы ответили что можно :))
Меня интересуют три заголовка: код ошибки, кодировка и Location.
2) При выполнении скрипт иногда зависает, ограничения на конект и время выполнения скрипта выставлены. Скрипт я тестирую на базе в несколько сотен url, и каждый раз он где-нибудь виснет, то после 100, то после 500, а иногда и после обработки 5 сайтов. Что это может быть и как с этим бороться? | |
|
|
|
|
|
|
|
для: kran
(20.10.2005 в 19:21)
| | 1) код идёт первой строкой - её нужно всегда смотреть, если код 200 - обрабатывать дальнейший поток как страницу, если код 301 или 302 - смотреть новый URL и грузить страницу от туда.
2) Ограничение по времени снято? У вас фигурирует 10 минут
<?php
set_time_limit(600);
?>
|
снимите вообще ограничения
<?php
set_time_limit(0); // бесконечное время
?>
|
| |
|
|
|
|
|
|
|
для: cheops
(20.10.2005 в 21:28)
| | 1) Про первую строку я понял, это легко. Значение кода будет всегда в массиве с индексом =0. А как выцепить остальные заголовки Location и Charset, если не циклом с проверкой?
2) У меня вывставлено ограничение выполнения скрипта на сутки, можно сказать на бесконечное время :)) Сервер стоит дома, ограничений никаких на нем нет, соединение с интернет постоянное. Почему виснет, незнаю?
Когда вместо сокетов использовал file_get_contents(), такого не было! Может в этом дело? | |
|
|
|
|
|
|
|
для: kran
(20.10.2005 в 21:42)
| | 1) Не очень понятно, т.е. нужно просто вытащить содержимое заголовков Location и Charset?
2) Хм... а соединение быстрое? Попробуйте уменьшить ожидание сокета с 30 секунд на меньшее (последний параметр fsockopen()) | |
|
|
|
|
|
|
|
для: cheops
(20.10.2005 в 22:39)
| | 1) Ну примерно так! Т.е. если код ошибки имеет постоянное место в массиве, то остальные заголовки выводятся, что называется - "как придется". По крайней мере просмотрев около 500 записей никакой закономерности я не обнаружил! Вот если бы массив можно было бы вернуть, скажем ассоциативным, тогда было бы другое дело!
Можно конечно весь массив перебрать и сравнить по шаблонам интересующие значения, но может быть есть какой-нибудь другой способ, более рациональный и удобный!
2) Cоединение 256 Kb.
Думаете, что надо именно уменьшить время ожидания?
Попробую, думаю 10 должно вполне хватить! | |
|
|
|
|
|
|
|
для: kran
(20.10.2005 в 23:50)
| | 1) Так а вы их просто в массив помещайте, а тело документа отдельно грузите... тогда вы сможете просматривать массив в цикле, только каждый раз после использования уничтожайте массив при помощи unset() иначе у вас будут старые заголовки в него просачиваться...
2) Ну при такой скорости можно и меньше - если сервер не отзывается за такое время при таком канале, он скорее всего не рабочий... | |
|
|
|
|
|
|
|
для: cheops
(21.10.2005 в 13:07)
| | 1) Вот именно так я и делаю, один в один :))) Просто мне думалось что для работы с заголовками должны быть специальные функции, вот например откопал getallheaders(), но она кажется не совсем подходит, может еще что есть?
2) Вроде бы проблема решена, по крайней мере 3 раза в цикле прогнал через скрипт 1000 url и не одного зависания! Сделал следующее: уменьшил время соединения до 10 и в конце цикла все используемые переменные добавил в unset(), там раньше были только переменные вида $var. , но на этот раз я туда добавил абсолютно всё!
Как выяснилось при отсутствии значения какой-нибудь переменной, она не уничтожалась, а передавалась с этим же значением в очередное вхождение в цикл, и тем самым вызывая сбой! | |
|
|
|
|
|
|
|
для: kran
(21.10.2005 в 13:33)
| | 1) Нет для работы с заголовками, которые получают сокеты специальных функций нет... в PHP используются только специфические функции, вроде setcookie(), session_start(), header()... | |
|
|
|
|
|
|
|
для: cheops
(21.10.2005 в 13:44)
| | Все понятно!
Огромное спасибо за внимание и помощь в решении данной проблемы!
Все работает отлично и только благодаря Вам!
Cheops вы СУПЕР, как ПРОГРАММИСТ и ЧЕЛОВЕК!
З.Ы.: Вам бы надо на сайте книгу отзывов сделать, для тех кому вы помогли.
Типа: Сайт->Проблема->Решение->Отзыв
Пусть народ знает своих героев :))) | |
|
|
|
|
|
|
|
для: cheops
(20.10.2005 в 00:33)
| | >PS Слушайте, а ведь действительно меняют кодировку в
>зависимости от пользовательского агента :))) дур дом, они на
>какое место в поисковых системах расчитывают...
Я тут вообще наткнулся на непонятные мне вещи www.stroipanorama.ru и www.termo-gs.ru, посмотрите как у них html записан! Вообще интересно зачем так делать? Непонятно! | |
|
|
| |
|
|
|
|
для: napTu3aH
(20.10.2005 в 20:00)
| | >Вам скорее всего нужна функция urldecode, вот темы в
>которых это подробнее обсуждается
>http://softtime.ru/forum/read.php?id_forum=1&id_theme=8172&page=1
>http://softtime.ru/forum/read.php?id_forum=1&id_theme=7442&page=1
Спасибо, но меня интересует немного другое :))) , например http-заголовки и работа с ними!
А этот пример я просто так привел, как продукт тестирования обсуждаемого скрипта, эта функция скорее админам этих сайтов пригодится :))
Конечно если такие сайты есть, то придется написать для них отдельное правило их обработки :) | |
|
|
|
|