Leon1010

Я в Соц.сетях:

Теги:

Ссылки

Получение контента средствами PHP

Получить контент другого сайта средствами PHP очень просто. Для этого существует ряд полезных функций, которые можно смело задействовать для этих целей. Самый простой вариант — получение контента при помощи функции file_get_contents. Достаточно передать URL в качестве параметра этой функции и она вернет полученный контент или false — в случае неудачи. Но мы легких путей не ищем, поэтому дальше рассмотрим более сложную функцию, обладающую рядом дополнительных и полезных качеств.

Полезными качествами, в данном контексте, будут возможность получения множества атрибутов запрашиваемого контента, а также возможность получения заголовка ответа сервера и времени выполнения запроса. Данная функция использует встроенные в PHP функции для работы с сокетами, которые предназначены для соединения клиента с сервером.

Итак посмотрим на саму функцию, а затем перейдем к описанию ее работы и применения.

<?php
function abi_get_url_object($url, $user_agent=null)
{
  define('ABI_URL_STATUS_UNSUPPORTED', 100);
  define('ABI_URL_STATUS_OK', 200);
  define('ABI_URL_STATUS_REDIRECT_301', 301);
  define('ABI_URL_STATUS_REDIRECT_302', 302);
  define('ABI_URL_STATUS_NOT_FOUND', 404);
  define('MAX_REDIRECTS_NUM', 4);
  $TIME_START = explode(' ', microtime());
  $TRY_ID = 0;
  $URL_RESULT = false;
  do
  {
    //--- parse URL ---
    $URL_PARTS = @parse_url($url);
    if( !is_array($URL_PARTS))
    {
      break;
    };
    $URL_SCHEME = ( isset($URL_PARTS['scheme']))?$URL_PARTS['scheme']:'http';
    $URL_HOST = ( isset($URL_PARTS['host']))?$URL_PARTS['host']:'';
    $URL_PATH = ( isset($URL_PARTS['path']))?$URL_PARTS['path']:'/';
    $URL_PORT = ( isset($URL_PARTS['port']))?intval($URL_PARTS['port']):80;
    if( isset($URL_PARTS['query']) && $URL_PARTS['query']!='' )
    {
      $URL_PATH .= '?'.$URL_PARTS['query'];
    };
    $URL_PORT_REQUEST = ( $URL_PORT == 80 )?'':":$URL_PORT";
    //--- build GET request ---
    $USER_AGENT = ( $user_agent == null )?'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)':strval($user_agent);
    $GET_REQUEST = "GET $URL_PATH HTTP/1.0\r\n"
    ."Host: $URL_HOST$URL_PORT_REQUEST\r\n"
    ."Accept: text/plain\r\n"
    ."Accept-Encoding: identity\r\n"
    ."User-Agent: $USER_AGENT\r\n\r\n";
    //--- open socket ---
    $SOCKET_TIME_OUT = 30;
    $SOCKET = @fsockopen($URL_HOST, $URL_PORT, $ERROR_NO, $ERROR_STR, $SOCKET_TIME_OUT);
    if( $SOCKET )
    {
     if( fputs($SOCKET, $GET_REQUEST))
     {
      socket_set_timeout($SOCKET, $SOCKET_TIME_OUT);
      //--- read header ---
      $header = '';
      $SOCKET_STATUS = socket_get_status($SOCKET);
      while( !feof($SOCKET) && !$SOCKET_STATUS['timed_out'] )
      {
        $temp = fgets($SOCKET, 128);
        if( trim($temp) == '' ) break;
        $header .= $temp;
        $SOCKET_STATUS = socket_get_status($SOCKET);
      };
      //--- get server code ---
      if( preg_match('~HTTP\/(\d+\.\d+)\s+(\d+)\s+(.*)\s*\\r\\n~si', $header, $res))
       $SERVER_CODE = $res[2];
      else
       break;
      if( $SERVER_CODE == ABI_URL_STATUS_OK )
      {
        //--- read content ---
        $content = '';
        $SOCKET_STATUS = socket_get_status($SOCKET);
        while( !feof($SOCKET) && !$SOCKET_STATUS['timed_out'] )
        {
          $content .= fgets($SOCKET, 1024*8);
          $SOCKET_STATUS = socket_get_status($SOCKET);
        };
        //--- time results ---
        $TIME_END = explode(' ', microtime());
        $TIME_TOTAL = ($TIME_END[0]+$TIME_END[1])-($TIME_START[0]+$TIME_START[1]);
        //--- output ---
        $URL_RESULT['header'] = $header;
        $URL_RESULT['content'] = $content;
        $URL_RESULT['time'] = $TIME_TOTAL;
        $URL_RESULT['description'] = '';
        $URL_RESULT['keywords'] = '';
        //--- title ---
        $URL_RESULT['title'] =( preg_match('~<title>(.*)<\/title>~U', $content, $res))?strval($res[1]):'';
        //--- meta tags ---
        if( preg_match_all('~<meta\s+name\s*=\s*["\']?([^"\']+)["\']?\s+content\s*=["\']?([^"\']+)["\']?[^>]+>~', $content, $res, PREG_SET_ORDER) > 0 )
        {
         foreach($res as $meta)
          $URL_RESULT[strtolower($meta[1])] = $meta[2];
        };
      }
      elseif( $SERVER_CODE == ABI_URL_STATUS_REDIRECT_301 || $SERVER_CODE == ABI_URL_STATUS_REDIRECT_302 )
      {
        if( preg_match('~location\:\s*(.*?)\\r\\n~si', $header, $res))
        {
         $REDIRECT_URL = rtrim($res[1]);
         $URL_PARTS = @parse_url($REDIRECT_URL);
         if( isset($URL_PARTS['scheme'])&& isset($URL_PARTS['host']))
          $url = $REDIRECT_URL;
         else
          $url = $URL_SCHEME.'://'.$URL_HOST.'/'.ltrim($REDIRECT_URL, '/');
        }
        else
        {
         break;
        };
      };
     };// GET request is OK
     fclose($SOCKET);
    }// socket open is OK
    else
    {
     break;
    };
    $TRY_ID++;
  }
  while( $TRY_ID <= MAX_REDIRECTS_NUM && $URL_RESULT === false );
  return $URL_RESULT;
};
?>

Итак, входящими параметрами являются: $url — строка, содержащая URL http-протокола, $user_agent — строка с любым юзер-агентом (если пропустить параметр или установить его в null — user_agent будет как в IE). Константа MAX_REDIRECTS_NUM устанавливает количество разрешенных редиректов (поддерживаются 301 и 302 редиректы).

Теперь перейдем к примерам практического использования этой функции:

<?php
$url = 'http://www.yahoo.com';
$user_agent = 'MySuperBot 1.02';
$URL_OBJ = abi_get_url_object($url, $user_agent);
if( $URL_OBJ )
{
  $CONTENT = $URL_OBJ['content'];
  $HEADER = $URL_OBJ['header'];
  $TITLE = $URL_OBJ['title'];
  $DESCRIPTION = $URL_OBJ['description'];
  $KEYWORDS = $URL_OBJ['keywords'];
  $TIME_REQUEST = $URL_OBJ['time'];
}
else
  print 'Запрашиваемая страница недоступна.';
?>

Как видно из вышеприведенного примера, мы можем получить всю информацию по запрошенному URL. Кроме того, можно получить значения любого мета-тега. Для этого можно воспользоваться следующим кодом:

<?php
preg_match ("/charset=(.*?)\"/is", $CONTENT, $char);
$charset=$char[1];
?>

Вышеприведенные примеры были протестированы в личных проектах (проверка обратных ссылок, доступность ресурсов). Надеюсь, что вам тоже удастся найти им достойное применение.

Запись опубликована в рубрике Кодинг с метками , .