CakePHP : Code/Components/Browser

Браузер

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

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

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


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

1. Добавьте в контроллер сверху
var $components = array('Browser');


2. В функции контроллера можно использовать
$body = $this->Browser->get('http://php.southpark.com.ua/');
$header = $this->Browser->header; // необязательно

Перед get, можно настроить параметры
$this->Browser->userAgent = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)';
$this->Browser->username = 'root';
$this->Browser->password = 'upyachka';
$this->Browser->proxy = '192.168.0.1:3128';
$this->Browser->referer = 'http://php.southpark.com.ua/';
$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
<?
/**
 * Эмулятор браузера
 *
 * @version 1.2 (14 Oct 2007)
 *
 */

class BrowserComponent extends Object {
    var 
$handle;
    var 
$header;
    var 
$body;
    var 
$userAgent 'random';

    
// если нужно логиниться
    
var $username null;
    var 
$password null;

    var 
$proxy ''// 'ip:port'
    
var $referer 'http://www.google.com/';
    var 
$timeout 30;

    
/**
     * Если вы хотите кешировать запросы, то создайте папку APP/tmp/cache/browser
     *
     * @var unknown_type
     */
    
var $cacheFolder null;

    var 
$symbolsNotFile = array( '~',  '!',  '@',  '#',  'http://''/',  "\\"':',  '*',  '?',  '"',  '<',  '>',  '|');
    var 
$symbolsFile = array('~~''!!''@@''##''#~''~!''~@''~#''!~''!@''!#''@~''@!''@#'); // ещё можно использовать  '#!', '#@'

    /**
     * Init handle for connection
     *
     * @param AppController $controller
     */
    
function startup(&$controller) {
        
$cacheFolder APP 'tmp' DS 'cache' DS 'browser' DS;
        if (
is_dir($cacheFolder)) {
            
$this->cacheFolder $cacheFolder;
        }
        
$this->_initUserAgent();
        
$this->handle curl_init();
    }

    function 
_setHeaderBody($response) {
        
$regex '/(.*?)\n[\r\n]*?\n+(.*)/sm';

        
$this->header '';
        if (!
preg_match($regex$response$m)) {
            
$this->body $response;
        } else {
            
$this->header $m[1];
            
$this->body ltrim($m[2], "\r");

            
// sometimes there are several headers
            
while (strpos($this->body'HTTP/')==&& preg_match($regex$this->body$m)) {
                
$this->header .= "\n\n" $m[1];
                
$this->body ltrim($m[2], "\r");
            }
        }

        return 
true;
    }

    
/**
     * Main function
     *
     * @param string $url
     * @param array $postvars
     * @return string body
     * after execution $this->header is accessible if needed
     */

    
function get($url$postvars=null) {
        if (!empty(
$this->cacheFolder) && empty($postvars)) {
            
$cacheFile $this->cacheFolder r($this->symbolsNotFile$this->symbolsFile$url).'.txt';
        } else {
            
$cacheFile null;
        }

        if (!empty(
$cacheFile) && file_exists($cacheFile)) {
            
$response file_get_contents($cacheFile);
        } else {
            
$this->prepare($url$postvars);
            
$response curl_exec($this->handle);
            if (!empty(
$cacheFile)) {
                
file_put_contents($cacheFile$response);
            }
        }
        
$this->referer $url;
        
$this->_setHeaderBody($response);

        return 
$this->body;
    }


    
/**
     * Set default options of curl
     *
     * @param string $url
     * @param array $postvars
     */

    
function prepare($url$postvars=false) {
        
curl_setopt($this->handleCURLOPT_PROXY$this->proxy);
        
curl_setopt($this->handleCURLOPT_REFERER$this->referer);
        
curl_setopt($this->handleCURLOPT_USERAGENT$this->userAgent);
        
curl_setopt($this->handleCURLOPT_URLstr_replace('&amp;','&',$url));
        
curl_setopt($this->handleCURLOPT_HEADER1);
        
curl_setopt($this->handleCURLOPT_FOLLOWLOCATION,1);
        
curl_setopt($this->handleCURLOPT_RETURNTRANSFER1);
        
curl_setopt($this->handleCURLOPT_TIMEOUT$this->timeout);
        
curl_setopt($this->handleCURLOPT_SSL_VERIFYPEERfalse);
        
curl_setopt($this->handleCURLOPT_SSL_VERIFYHOST,  2);

        
curl_setopt($this->handleCURLOPT_COOKIEJARAPP.'tmp/cookie.txt');
        
curl_setopt($this->handleCURLOPT_COOKIEFILEAPP.'tmp/cookie.txt');
        if (!empty(
$postvars)) {
            
curl_setopt($this->handleCURLOPT_POST1);
            
curl_setopt($this->handleCURLOPT_POSTFIELDS$postvars);
        }

        if (!empty(
$this->username)) {
            
curl_setopt($this->handleCURLOPT_HTTPAUTHCURLAUTH_ANY);
            
curl_setopt($this->handleCURLOPT_USERPWD$this->username.':'.$this->password); // $auth should be [username]:[password]
        
}

        return 
true;
    }

    
/**
     * Close current connection
     *
     */

    
function close() {
        
curl_close($this->handle);
        return 
true;
    }

    
/**
     * Clears cache
     */
    
function clearCache() {
        if (empty(
$this->cacheFolder)) return false;
        
$dir dir($this->cacheFolder);
        while ((
$file $dir->read()) !== false) {
            if (
in_array($file, array('''.''..'))) continue;
            
unlink($dir->path $file);
        }
        return 
true;
    }

    
/**
     * What browser should be emulated
     *
     * @return string browser name
     */
    
function _initUserAgent() {
        if (
$this->userAgent!='random') return true;

        
$browsers = array(
            
'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 1.1.4322)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser; .NET CLR 2.0.50727)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.10',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts)',
            
'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)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ru) Opera 8.50',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ru) Opera 8.54',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705)',
            
'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)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)',
            
'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)',
            
'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)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.1)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)',
            
'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)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.7 (build 01670); .NET CLR 1.1.4322)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.7 (build 01670); InfoPath.1)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.8 (build 01709))',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.8 (build 01709); .NET CLR 1.1.4322)',
            
'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)',
            
'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)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; InfoPath.1)',
            
'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)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)',
            
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.1)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser; Avant Browser; .NET CLR 1.1.4322)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon; Avant Browser; InfoPath.2)',
            
'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)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MRA 4.6 (build 01425); InfoPath.1)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MRA 4.8 (build 01709))',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MRA 4.8 (build 01709); .NET CLR 1.1.4322; InfoPath.1)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MRA 4.8 (build 01709); Avant Browser)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MRA 4.9 (build 01863); .NET CLR 2.0.50727)',
            
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; MyIE2)',
            
'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)',
            
'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)',
            
'Mozilla/5.0 (Windows; U; Windows NT 5.1; bg; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3',
            
'Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.0.11) Gecko/20070312 Firefox/1.5.0.11',
            
'Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3',
            
'Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4',
            
'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3',
            
'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3',
            
'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4',
            
'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.0.11) Gecko/20070312 Firefox/1.5.0.11',
            
'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3',
            
'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4',
            
'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.12) Gecko/20050919 Firefox/1.0.7',
            
'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',
            
'Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.8) Gecko/20060112 ASPLinux/1.5-1.2am Firefox/1.5',
            
'Opera/8.54 (Windows NT 5.1; U; en)',
            
'Opera/9.00 (Windows NT 5.1; U; ru)',
            
'Opera/9.01 (Windows NT 5.1; U; ru)',
            
'Opera/9.02 (Windows NT 5.0; U; ru)',
            
'Opera/9.02 (Windows NT 5.1; U; ru)',
            
'Opera/9.02 (Windows NT 5.2; U; en)',
            
'Opera/9.10 (Windows NT 5.1; U; ru)',
            
'Opera/9.20 (Windows NT 5.1; U; en)',
            
'Opera/9.20 (Windows NT 5.1; U; ru)',
            
'Opera/9.21 (Windows NT 5.1; U; ru)',
        );

        
$this->userAgent $browsers[array_rand($browsers)];
        return 
true;
    }
}
?>