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;

    }

}

?>