компонент для CakePHP Как создать свой сайт > Вебмастеру > Создание своего сайта > Browser: компонент для CakePHP

Browser: компонент для CakePHP

Развлечение у меня единственное — сигареты. Я научился курить под душем…
«Зона. Записки надзирателя», Сергей Довлатов.
14 октября 2007

    Мне часто приходится обрабатывать информацию с других сайтов и наконец я решил написать свой компонент Browser.


    Функциональные возможности

  • Корректно разделяет header и body
  • Может кешировать запросы
  • Может отправлять POST-запросы
  • Может работать через proxy
  • Поддерживает cookies
  • Может автоматически вводить имя пользователя и пароль
  • Автоматически подставляет referer с прошлой страницы (можно установить свой)
  • Подставляет нормальный UserAgent, чтобы сайты не думали, что это робот

    Использовать компонент, как и все компоненты для CakePHP очень легко.

1. Добавьте в контроллер сверху

  1. var $components = array('Browser');

2. В функции контроллера можно использовать

  1. $body = $this->Browser->get('http://www.seoded.ru/');
  2. $header = $this->Browser->header; // необязательно

    Перед get, можно настроить параметры

  1. $this->Browser->userAgent = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)';
  2. $this->Browser->username = 'root';
  3. $this->Browser->password = 'upyachka';
  4. $this->Browser->proxy = '192.168.0.1:3128';
  5. $this->Browser->referer = 'http://www.seoded.ru/';
  6. $this->Browser->timeout = 10; // по умолчанию 30 секунд

    Правильно было бы написать тест, который проверяет все функции, но я и так молодец, что написал хоть какой-то тест

    Когда вы пишете свои компоненты, не забывайте писать тесты.

    Кстати, корректно разбивать header и body не так просто. В идеале, они должны разделяться \r\n\r\n. Но на практике мне встечались \r\n\n\r\n\n и \n\r\n\r. Вдобавок иногда бывает несколько header, например, при redirect.

    Для того, чтобы заработало кеширование, создайте папку APP/tmp/cache/browser и дайте права на запись в неё. Чтобы работали cookie, дайте права на запись в папку APP/tmp. Там будет создан файл cookie.txt.

    Остальные функции — это просто обёртка над CURL.

app\controllers\components\browser.php

  1. <?
  2.  
  3. /**
  4. * Emulation of browser
  5. *
  6. * @version 1.2 (14 Oct 2007)
  7. *
  8. */
  9. class BrowserComponent extends Object {
  10.     var $handle;
  11.     var $header;
  12.     var $body;
  13.  
  14.     var $userAgent = 'random';
  15.  
  16.     // если нужно логиниться
  17.     var $username = null;
  18.     var $password = null;
  19.  
  20.     var $proxy = ''; // 'ip:port'
  21.     var $referer = 'http://www.google.com/';
  22.     var $timeout = 30;
  23.  
  24.     /**
  25.      * if you want to cache your requests then create folder APP/tmp/cache/browser
  26.      *
  27.      * @var unknown_type
  28.      */
  29.     var $cacheFolder = null;
  30.  
  31.     var $symbolsNotFile = array( '~''!''@''#''http://', '/'"\\", ':''*''?''"''<''>''|');
  32.     var $symbolsFile = array('~~', '!!', '@@', '##', '#~',      '~!', '~@', '~#', '!~', '!@', '!#', '@~', '@!', '@#'); // ещё можно использовать  '#!', '#@'
  33.  
  34.     /**
  35.      * Init handle for connection
  36.      *
  37.      * @param AppController $controller
  38.      */
  39.     function startup(&$controller) {
  40.         $cacheFolder = APP . 'tmp' . DS . 'cache' . DS . 'browser' . DS;
  41.         if (is_dir($cacheFolder)) {
  42.             $this->cacheFolder = $cacheFolder;
  43.         }
  44.  
  45.         $this->_initUserAgent();
  46.  
  47.         $this->handle = curl_init();
  48.     }
  49.  
  50.     function _setHeaderBody($response) {
  51.         $regex = '/(.*?)\n[\r\n]*?\n+(.*)/sm';
  52.  
  53.         $this->header = '';
  54.         if (!preg_match($regex, $response, $m)) {
  55.             $this->body = $response;
  56.         } else {
  57.             $this->header = $m[1];
  58.             $this->body = ltrim($m[2], "\r");
  59.  
  60.             // sometimes there are several headers
  61.             while (strpos($this->body, 'HTTP/')==0 && preg_match($regex, $this->body, $m)) {
  62.                 $this->header .= "\n\n" . $m[1];
  63.                 $this->body = ltrim($m[2], "\r");
  64.             }
  65.         }
  66.  
  67.         return true;
  68.     }
  69.  
  70.     /**
  71.      * Main function
  72.      *
  73.      * @param string $url
  74.      * @param array $postvars
  75.      * @return string body
  76.      * after execution $this->header is accessible if needed
  77.      */
  78.     function get($url, $postvars=null) {
  79.         if (!empty($this->cacheFolder) && empty($postvars)) {
  80.             $cacheFile = $this->cacheFolder . r($this->symbolsNotFile, $this->symbolsFile, $url).'.txt';
  81.         } else {
  82.             $cacheFile = null;
  83.         }
  84.  
  85.         if (!empty($cacheFile) && file_exists($cacheFile)) {
  86.             $response = file_get_contents($cacheFile);
  87.         } else {
  88.             $this->prepare($url, $postvars);
  89.             $response = curl_exec($this->handle);
  90.             if (!empty($cacheFile)) {
  91.                 file_put_contents($cacheFile, $response);
  92.             }
  93.         }
  94.         $this->referer = $url;
  95.  
  96.         $this->_setHeaderBody($response);
  97.  
  98.         return $this->body;
  99.     }
  100.  
  101.     /**
  102.      * Set default options of curl
  103.      *
  104.      * @param string $url
  105.      * @param array $postvars
  106.      */
  107.     function prepare($url, $postvars=false){
  108.         curl_setopt($this->handle, CURLOPT_PROXY, $this->proxy);
  109.         curl_setopt($this->handle, CURLOPT_REFERER, $this->referer);
  110.         curl_setopt($this->handle, CURLOPT_USERAGENT, $this->userAgent);
  111.         curl_setopt($this->handle, CURLOPT_URL, str_replace('&amp;','&',$url));
  112.         curl_setopt($this->handle, CURLOPT_HEADER, 1);
  113.         curl_setopt($this->handle, CURLOPT_FOLLOWLOCATION,1);
  114.         curl_setopt($this->handle, CURLOPT_RETURNTRANSFER, 1);
  115.         curl_setopt($this->handle, CURLOPT_TIMEOUT, $this->timeout);
  116.         curl_setopt($this->handle, CURLOPT_SSL_VERIFYPEER, false);
  117.         curl_setopt($this->handle, CURLOPT_SSL_VERIFYHOST,  2);
  118.  
  119.         curl_setopt($this->handle, CURLOPT_COOKIEJAR, APP.'tmp/cookie.txt');
  120.         curl_setopt($this->handle, CURLOPT_COOKIEFILE, APP.'tmp/cookie.txt');
  121.  
  122.         if (!empty($postvars)){
  123.             curl_setopt($this->handle, CURLOPT_POST, 1);
  124.             curl_setopt($this->handle, CURLOPT_POSTFIELDS, $postvars);
  125.         }
  126.  
  127.         if (!empty($this->username)) {
  128.             curl_setopt($this->handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
  129.             curl_setopt($this->handle, CURLOPT_USERPWD, $this->username.':'.$this->password); // $auth should be [username]:[password]
  130.         }
  131.  
  132.         return true;
  133.     }
  134.  
  135.     /**
  136.      * Close current connection
  137.      *
  138.      */
  139.     function close() {
  140.         curl_close($this->handle);
  141.         return true;
  142.     }
  143.  
  144.     /**
  145.      * Clears cache
  146.      */
  147.     function clearCache() {
  148.         if (empty($this->cacheFolder)) return false;
  149.  
  150.         $dir = dir($this->cacheFolder);
  151.         while (($file = $dir->read()) !== false) {
  152.             if (in_array($file, array('', '.', '..'))) continue;
  153.  
  154.             unlink($dir->path . $file);
  155.         }
  156.  
  157.         return true;
  158.     }
  159.  
  160.     /**
  161.      * What browser should be emulated
  162.      *
  163.      * @return string browser name
  164.      */
  165.     function _initUserAgent() {
  166.         if ($this->userAgent!='random') return true;
  167.  
  168.         $browsers = array(
  169.             'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)',
  170.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)',
  171.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
  172.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)',
  173.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 1.1.4322)',
  174.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser; .NET CLR 2.0.50727)',
  175.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.10',
  176.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts)',
  177.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MRA 4.8 (build 01709); Maxthon; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
  178.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ru) Opera 8.50',
  179.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ru) Opera 8.54',
  180.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)',
  181.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705)',
  182.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727)',
  183.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)',
  184.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)',
  185.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; MAXTHON 2.0)',
  186.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)',
  187.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.1)',
  188.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)',
  189.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; InfoPath.2; .NET CLR 1.1.4322; MAXTHON 2.0)',
  190.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)',
  191.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2)',
  192.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.7 (build 01670); .NET CLR 1.1.4322)',
  193.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.7 (build 01670); InfoPath.1)',
  194.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.8 (build 01709))',
  195.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.8 (build 01709); .NET CLR 1.1.4322)',
  196.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.8 (build 01709); .NET CLR 2.0.50727; InfoPath.2; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30)',
  197.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.8 (build 01709); Maxthon; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30)',
  198.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; InfoPath.1)',
  199.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; MRA 4.8 (build 01709); .NET CLR 1.1.4322; InfoPath.1)',
  200.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)',
  201.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)',
  202.             'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
  203.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
  204.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322)',
  205.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)',
  206.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)',
  207.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.1)',
  208.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser; Avant Browser; .NET CLR 1.1.4322)',
  209.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon)',
  210.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon; Avant Browser; InfoPath.2)',
  211.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon; MyIE2; .NET CLR 1.0.3705; .NET CLR 2.0.50727; InfoPath.2)',
  212.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MRA 4.6 (build 01425); InfoPath.1)',
  213.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MRA 4.8 (build 01709))',
  214.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MRA 4.8 (build 01709); .NET CLR 1.1.4322; InfoPath.1)',
  215.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MRA 4.8 (build 01709); Avant Browser)',
  216.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MRA 4.9 (build 01863); .NET CLR 2.0.50727)',
  217.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MyIE2)',
  218.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MyIE2; .NET CLR 2.0.50727; InfoPath.1; .NET CLR 1.1.4322; MEGAUPLOAD 1.0)',
  219.             'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; InfoPath.2; .NET CLR 1.1.4322)',
  220.             'Mozilla/5.0 (Windows; U; Windows NT 5.1; bg; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3',
  221.             'Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.0.11) Gecko/20070312 Firefox/1.5.0.11',
  222.             'Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3',
  223.             'Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4',
  224.             'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3',
  225.             'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3',
  226.             'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4',
  227.             'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.0.11) Gecko/20070312 Firefox/1.5.0.11',
  228.             'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3',
  229.             'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4',
  230.             'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.12) Gecko/20050919 Firefox/1.0.7',
  231.             'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.1) Gecko/20060313 Fedora/1.5.0.1-9 Firefox/1.5.0.1 pango-text',
  232.             'Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.8) Gecko/20060112 ASPLinux/1.5-1.2am Firefox/1.5',
  233.             'Opera/8.54 (Windows NT 5.1; U; en)',
  234.             'Opera/9.00 (Windows NT 5.1; U; ru)',
  235.             'Opera/9.01 (Windows NT 5.1; U; ru)',
  236.             'Opera/9.02 (Windows NT 5.0; U; ru)',
  237.             'Opera/9.02 (Windows NT 5.1; U; ru)',
  238.             'Opera/9.02 (Windows NT 5.2; U; en)',
  239.             'Opera/9.10 (Windows NT 5.1; U; ru)',
  240.             'Opera/9.20 (Windows NT 5.1; U; en)',
  241.             'Opera/9.20 (Windows NT 5.1; U; ru)',
  242.             'Opera/9.21 (Windows NT 5.1; U; ru)',
  243.             );
  244.  
  245.         $this->userAgent = $browsers[array_rand($browsers)];
  246.         return true;
  247.     }
  248. }
  249.  
  250. ?>

Автор: Владимир Лучанинов.

Комментарии:

Антон Исайкин
2008-01-13 13:44:44
Владимир, вот вам еще случай, символов, отделяющих хеадер, которые не верно распознает ваш браузер. Сайт ***.

Artur
2008-01-26 22:41:37
Интересно конечно, но самый оптимальный вариант отделения HEADERS это вырезать хедер и смотреть наличие html тегов в хедере. Если хтмл нету, то правильно отрезали.


⇓ 

Поделись ссылкой на Seoded.ru с друзьями, знакомыми и собеседниками в соцсетях и на форумах! А сам сайт добавь в закладки! Так победим.

Поделиться ссылкой на эту страницу в:

Полезные ссылки:

Заработай на фотостоках денег Фотографу в Интернете рады

Ещё материалы по этой теме:

Скажи кэшированию… иногда. Часть 2: Memcache Скажи кешированию… иногда :) Управление зависимостями в PHP-коде Инверсия зависимостей Registry вместо Singleton
основан в 2008 г. © Все права на материалы сайта Seoded.ru принадлежат Алексею Вострову.
Копирование (полное или частичное) любых материалов сайта возможно только с разрешения автора и при указании ссылки на источник.
Ослушавшихся находит и забирает Бабайка!