Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: http-заголовки
 
 автор: kran   (17.10.2005 в 14:59)   письмо автору
 
 

Здравствуйте!

Как прочесть 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

   
 
 автор: cheops   (17.10.2005 в 19:19)   письмо автору
 
   для: kran   (17.10.2005 в 14:59)
 

Это можно сделать при помощи следующего скрпта
<?php 
  
// А это сама функция узнавания размера 
  
function get_content($hostname$path)
  { 
    
$line "";
    
// Устанавливаем соединение, имя которого
    // передано в параметре $hostname
    
$fp fsockopen($hostname80$errno$errstr30); 
    
// Проверяем успешность установки соединения
    
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($fp1024); 
        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 

   
 
 автор: kran   (17.10.2005 в 21:24)   письмо автору
 
   для: cheops   (17.10.2005 в 19:19)
 

1) А можно получить только определенные, интересующие заголовки, или надо все циклом перебирать?

2)Относятся ли значения title и description к заголовкам?

3)Что лучше использовать при определении кодировки страницы, значение которое возвращает сервер в заголовке или значения из мета-тега?

Как поступить в случае когда сервер не отдает заголовка с кодировкой, а в мета-теге кодировка указана, или наоборот? Пример: www.google.ru

Или вариант, когда сайт находится у хостера, где сервер при запросе отдает одну кодировку, а на сайте, в мета-теге указана другая?

P.S.: Очепятка в строке $end = $false;

   
 
 автор: cheops   (17.10.2005 в 23:33)   письмо автору
 
   для: kran   (17.10.2005 в 21:24)
 

1) Да можно любые - это уже технический вопрос
2) Нет они к HTTP-заголовкам не относятся, к ним относятся только META-заголовки с атрибутами HTTP-EQUIV и CONTENT - это в общем и есть альтернативный способ их указания.
<meta HTTP-EQUIV="Expires" CONTENT="0">

3) Лучше из META-тэга, разработчику виднее в какой кодировке страница. Если есть META-заголовок с кодировкой - всегда берите от туда.

   
 
 автор: kran   (18.10.2005 в 00:15)   письмо автору
 
   для: 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 , и в результате в индексе крякозябры.

   
 
 автор: cheops   (18.10.2005 в 13:50)   письмо автору
 
   для: kran   (18.10.2005 в 00:15)
 

1) Да.
2) Тут следует отталкиваться от следующего. В конфигурационном файле httpd.conf можно выставить кодировку по умолчанию. Именно такую кодировку сервер будет отправлять в HTTP-заголовке. Однако она может не совпадать с кодировкой реальных страниц, так как один разработчик будет использовать cp-1251, другой koi8-r, третий utf-8, сервер не может анализировать где какая кодировка - он шлёт то, что у него выставлено в конфиге. Разработчик с другой стороны всегда знает какая у него кодировка на странице и выставляет её правильно. Поэтому браузер в первую очередь ориентируется на META-заголовки и лишь затем на HTTP-заголовки сервера.

   
 
 автор: kran   (18.10.2005 в 15:31)   письмо автору
 
   для: 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 сайтом, то это зараза сводит на нет всю работу!

Что с этой гадостью можно сделать?
Помогите ;-))

   
 
 автор: cheops   (18.10.2005 в 20:54)   письмо автору
 
   для: kran   (18.10.2005 в 15:31)
 

Хм... загрузил www.abok.ru и ww.s-h.ru - указано windows-1251 и текст в windows-1251... Вы каким кодом загружаете страницу?

   
 
 автор: kran   (19.10.2005 в 12:23)   письмо автору
 
   для: 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 - там все получается как надо!

   
 
 автор: cheops   (19.10.2005 в 14:31)   письмо автору
 
   для: kran   (19.10.2005 в 12:23)
 

Хм... похоже он реагирует на USER_AGENT сервера, в котором обычно пишется PHP - можно попробовать подделать пользовательский агент, но тогда необходимо переходить на сокеты.

   
 
 автор: kran   (19.10.2005 в 16:34)   письмо автору
 
   для: cheops   (19.10.2005 в 14:31)
 

Из ваших слов понял, что еще не все потеряно? ;-))
Только что конкретно надо делать непонял :((

А вы не могли бы превести пример!

З.Ы.: Сегодня в Ozon.ru купил вашу книгу, та которая самая толстая и с CD! :-))
Буду ждать когда придет, очень надеюсь что поможет!

   
 
 автор: cheops   (19.10.2005 в 17:01)   письмо автору
 
   для: 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   (19.10.2005 в 21:54)   письмо автору
 
   для: kran   (17.10.2005 в 14:59)
 

Че то ничего не понимаю!
Похоже я уже туплю и что-то делаю не так :((



<?php

set_time_limit
(600);

$url="www.abok.ru"
$fp fsockopen($url80$errno$errstr30); 
  
  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($fp3000); 
  
    
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"

?>

   
 
 автор: cheops   (20.10.2005 в 00:33)   письмо автору
 
   для: kran   (19.10.2005 в 21:54)
 

Нет, от цикла здесь избавиться нельзя
<?php 

  set_time_limit
(600); 

  
$url="www.abok.ru"
  
$fp fsockopen($url80$errno$errstr30); 
  
$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($fp3000); 
    }
   
    
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 Слушайте, а ведь действительно меняют кодировку в зависимости от пользовательского агента :))) дур дом, они на какое место в поисковых системах расчитывают...

   
 
 автор: kran   (20.10.2005 в 19:21)   письмо автору
 
   для: cheops   (20.10.2005 в 00:33)
 

Все супер! Работает отлично, но нашел еще пару проблем!

1) При запросе определенных сайтов, сервер возвращает код 301 или 302, адрес редиректа посылается сервером в заголовке "Location". Т.е. все что нужно сделать это написать условие: если есть код редиректа, то брать url из заголовка Location. Вопрос можно ли выцепить нужный мне заголовок, или нужно перебирать весь массив который выдает сервер?
Я этот вопрос уже задавал и вы ответили что можно :))
Меня интересуют три заголовка: код ошибки, кодировка и Location.

2) При выполнении скрипт иногда зависает, ограничения на конект и время выполнения скрипта выставлены. Скрипт я тестирую на базе в несколько сотен url, и каждый раз он где-нибудь виснет, то после 100, то после 500, а иногда и после обработки 5 сайтов. Что это может быть и как с этим бороться?

   
 
 автор: cheops   (20.10.2005 в 21:28)   письмо автору
 
   для: kran   (20.10.2005 в 19:21)
 

1) код идёт первой строкой - её нужно всегда смотреть, если код 200 - обрабатывать дальнейший поток как страницу, если код 301 или 302 - смотреть новый URL и грузить страницу от туда.

2) Ограничение по времени снято? У вас фигурирует 10 минут
<?php
  set_time_limit
(600);
?>

снимите вообще ограничения
<?php
  set_time_limit
(0); // бесконечное время
?>

   
 
 автор: kran   (20.10.2005 в 21:42)   письмо автору
 
   для: cheops   (20.10.2005 в 21:28)
 

1) Про первую строку я понял, это легко. Значение кода будет всегда в массиве с индексом =0. А как выцепить остальные заголовки Location и Charset, если не циклом с проверкой?

2) У меня вывставлено ограничение выполнения скрипта на сутки, можно сказать на бесконечное время :)) Сервер стоит дома, ограничений никаких на нем нет, соединение с интернет постоянное. Почему виснет, незнаю?
Когда вместо сокетов использовал file_get_contents(), такого не было! Может в этом дело?

   
 
 автор: cheops   (20.10.2005 в 22:39)   письмо автору
 
   для: kran   (20.10.2005 в 21:42)
 

1) Не очень понятно, т.е. нужно просто вытащить содержимое заголовков Location и Charset?
2) Хм... а соединение быстрое? Попробуйте уменьшить ожидание сокета с 30 секунд на меньшее (последний параметр fsockopen())

   
 
 автор: kran   (20.10.2005 в 23:50)   письмо автору
 
   для: cheops   (20.10.2005 в 22:39)
 

1) Ну примерно так! Т.е. если код ошибки имеет постоянное место в массиве, то остальные заголовки выводятся, что называется - "как придется". По крайней мере просмотрев около 500 записей никакой закономерности я не обнаружил! Вот если бы массив можно было бы вернуть, скажем ассоциативным, тогда было бы другое дело!
Можно конечно весь массив перебрать и сравнить по шаблонам интересующие значения, но может быть есть какой-нибудь другой способ, более рациональный и удобный!

2) Cоединение 256 Kb.
Думаете, что надо именно уменьшить время ожидания?
Попробую, думаю 10 должно вполне хватить!

   
 
 автор: cheops   (21.10.2005 в 13:07)   письмо автору
 
   для: kran   (20.10.2005 в 23:50)
 

1) Так а вы их просто в массив помещайте, а тело документа отдельно грузите... тогда вы сможете просматривать массив в цикле, только каждый раз после использования уничтожайте массив при помощи unset() иначе у вас будут старые заголовки в него просачиваться...
2) Ну при такой скорости можно и меньше - если сервер не отзывается за такое время при таком канале, он скорее всего не рабочий...

   
 
 автор: kran   (21.10.2005 в 13:33)   письмо автору
 
   для: cheops   (21.10.2005 в 13:07)
 

1) Вот именно так я и делаю, один в один :))) Просто мне думалось что для работы с заголовками должны быть специальные функции, вот например откопал getallheaders(), но она кажется не совсем подходит, может еще что есть?

2) Вроде бы проблема решена, по крайней мере 3 раза в цикле прогнал через скрипт 1000 url и не одного зависания! Сделал следующее: уменьшил время соединения до 10 и в конце цикла все используемые переменные добавил в unset(), там раньше были только переменные вида $var. , но на этот раз я туда добавил абсолютно всё!
Как выяснилось при отсутствии значения какой-нибудь переменной, она не уничтожалась, а передавалась с этим же значением в очередное вхождение в цикл, и тем самым вызывая сбой!

   
 
 автор: cheops   (21.10.2005 в 13:44)   письмо автору
 
   для: kran   (21.10.2005 в 13:33)
 

1) Нет для работы с заголовками, которые получают сокеты специальных функций нет... в PHP используются только специфические функции, вроде setcookie(), session_start(), header()...

   
 
 автор: kran   (21.10.2005 в 13:56)   письмо автору
 
   для: cheops   (21.10.2005 в 13:44)
 

Все понятно!
Огромное спасибо за внимание и помощь в решении данной проблемы!
Все работает отлично и только благодаря Вам!
Cheops вы СУПЕР, как ПРОГРАММИСТ и ЧЕЛОВЕК!

З.Ы.: Вам бы надо на сайте книгу отзывов сделать, для тех кому вы помогли.
Типа: Сайт->Проблема->Решение->Отзыв
Пусть народ знает своих героев :)))

   
 
 автор: kran   (20.10.2005 в 19:35)   письмо автору
 
   для: cheops   (20.10.2005 в 00:33)
 

>PS Слушайте, а ведь действительно меняют кодировку в
>зависимости от пользовательского агента :))) дур дом, они на
>какое место в поисковых системах расчитывают...

Я тут вообще наткнулся на непонятные мне вещи www.stroipanorama.ru и www.termo-gs.ru, посмотрите как у них html записан! Вообще интересно зачем так делать? Непонятно!

   
 
 автор: napTu3aH   (20.10.2005 в 20:00)   письмо автору
 
   для: kran   (20.10.2005 в 19:35)
 

Вам скорее всего нужна функция 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

   
 
 автор: kran   (20.10.2005 в 20:37)   письмо автору
 
   для: napTu3aH   (20.10.2005 в 20:00)
 

>Вам скорее всего нужна функция urldecode, вот темы в
>которых это подробнее обсуждается
>http://softtime.ru/forum/read.php?id_forum=1&amp;id_theme=8172&amp;page=1
>http://softtime.ru/forum/read.php?id_forum=1&amp;id_theme=7442&amp;page=1

Спасибо, но меня интересует немного другое :))) , например http-заголовки и работа с ними!

А этот пример я просто так привел, как продукт тестирования обсуждаемого скрипта, эта функция скорее админам этих сайтов пригодится :))

Конечно если такие сайты есть, то придется написать для них отдельное правило их обработки :)

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования