Продемонстрирую работу своей небольшой библиотечки. Выкалдываю исключительно для критики, код сыроват, но использование в любых целях возможно и допустимо. На самом деле библиотечка значительно больше, уже почти доросла до фреймворка, на котором я строил ботов для контакта и одноклассников, но другие классы ещё не готовы для опубликования - слишком многое хочется изменить и улучшить. Вот урезанная библиотека: PHP: <?php /** * aquascript - helpers for webscripts * v 2.0 @ 18.06.2009-11.07.2009 * by deex icq 86776690 Freedomscripts.org */ class aquaCurl { private $ptr = 0; private $lastResponse = ''; // все ключи описаны в конце этого скрипта private $options = array( CURLOPT_URL => '', CURLOPT_POST => 0, // method POST CURLOPT_HEADER => 1, // show headers CURLOPT_NOBODY => 0, // disable body CURLOPT_FAILONERROR => 0, CURLOPT_TIMEOUT => 3600, CURLOPT_VERBOSE => 1, CURLOPT_FOLLOWLOCATION => 1, CURLOPT_POSTFIELDS => '', // post data. Content-Type: ARRAY - multipart/form-data, STRING - application/x-www-form-urlencoded CURLOPT_RETURNTRANSFER => 1, // return response CURLOPT_SSL_VERIFYPEER => 0, // verify ssl sertificat CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)', CURLOPT_TIMEOUT => 30, // CURLOPT_HTTPHEADER => array("Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7;","Keep-Alive: 300","Connection: keep-alive","Accept: */*") ); private $settingsRestore = array(); public $login = ''; public $pass = ''; // reset options public function rst() { $this->options = $this->settingsRestore; } function __construct() { if (!extension_loaded('curl')) if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') dl('curl.dll'); else dl('curl.so'); if (!extension_loaded('curl')) die("<b>Unable to load extension Curl! Application Exit</b><br/>"); $this->settingsRestore = $this->options; } public function setAuth($login, $pass) { $this->login = $login; $this->pass = $pass; } public function set($key, $val) { $this->options[$key] = $val; } public function exec($return = 1) { $this->ptr = curl_init(); if(!$this->ptr) die('curl not initialized'); if($this->options[CURLOPT_POSTFIELDS] != '' || sizeof($this->options[CURLOPT_POSTFIELDS]) > 1) $this->options[CURLOPT_POST] = 1; curl_setopt($this->ptr, CURLOPT_RETURNTRANSFER, $this->options[CURLOPT_RETURNTRANSFER]); curl_setopt_array($this->ptr, $this->options); $this->lastResponse = curl_exec($this->ptr); if($return) return $this->lastResponse; else return $this; } public function debug() { $response = '<strong>Info</strong><br /><br />'; $info = curl_getinfo($this->ptr); foreach($info as $k => $v) { if(strstr($k, 'size')) $v = ($v / 1024) . ' kb'; $response .= '<span style="color: #777">'.$k.':</span> '.$v.'<br />'; } $response .= '<br />'; if($errNo = curl_errno($this->ptr)) $response .= '<strong>Error #'.$errNo.':</strong> '.curl_error($this->ptr).'<br />'; return $response; } public function getResponseCode() { return curl_getinfo($this->ptr, CURLINFO_HTTP_CODE); } public function getCookie() { $parse = array(); preg_match_all("/Set-Cookie: ([0-9a-zA-Z\_\-=]*); /i", $this->lastResponse, $parse); return (isset($parse[1]) && sizeof($parse[1]))? implode('; ', $parse[1]) : ''; } public function setCookie($cookie) { $this->options[CURLOPT_COOKIE] = trim($cookie); return $this; } public function clearCookie() { $this->options[CURLOPT_COOKIE] = ''; return $this; } function __destruct() { if($this->ptr) curl_close($this->ptr); if(isset($_SESSION['curl_cookies'])) unset($_SESSION['curl_cookies']); } } //============================================================================== class antiCaptcha { private $timeOut = 5; // timeout before read result private $acKey = ''; // ac-service.info key private $captchaID = 0; // when service get captcha - its return captcha id private $imageType = 'jpg'; private $url = array( 'sendcaptcha' => 'http://ac-service.info/in.php', 'getinfo' => 'http://ac-service.info/res.php'); private $codes = array( 'in' => array( 'ERROR_KEY_DOES_NOT_EXIST' => 'incorrect anti-captcha key', 'ERROR_NO_SLOT_AVAILABLE' => 'service busy, please try later', 'ERROR_ZERO_CAPTCHA_FILESIZE' => 'captcha is empty file', 'ERROR_TOO_BIG_CAPTCHA_FILESIZE' => 'captcha size bigger than 30 kb', 'ERROR_WRONG_FILE_EXTENSION' => 'incorrect file extension (gif,jpg,png)' ), 'res' => array( 'ERROR_KEY_DOES_NOT_EXIST' => 'incorrect anti-captcha key', 'ERROR_WRONG_ID_FORMAT' => 'uploaded captcha ID is not a number', 'ERROR_NO_SUCH_CAPCHA_ID' => 'uploaded captcha ID is incorrect', 'ERROR_URL_METHOD_FORBIDDEN' => 'method disabled', 'CAPCHA_NOT_READY' => 'please wait..', 'OK_REPORT_RECORDED' => 'complaint writed (only for reportbad function)', ) ); private $captchaBody = ''; private $curl = ''; public $error = ''; public function __construct($acKey, $timeOut = 5, $imageType = 'jpg', $curl) { $this->timeOut = $timeOut; $this->acKey = $acKey; $this->imageType = $imageType; $this->curl = &$curl; } public function get($url, $cookie = '') { $this->curl->rst(); $this->curl->set(CURLOPT_URL, $url); $this->curl->set(CURLOPT_BINARYTRANSFER, 1); $this->curl->set(CURLOPT_HEADER, 0); if($cookie) $this->curl->setCookie($cookie); else $this->curl->clearCookie(); $this->captchaBody = $this->curl->exec(); return ($this->captchaBody)? 1 : 0; } // get captcha body public function send() { $postData = array( 'method' => 'base64', 'key' => $this->acKey, 'body' => base64_encode($this->captchaBody), 'ext' => $this->imageType ); $this->curl->rst(); $this->curl->set(CURLOPT_URL, $this->url['sendcaptcha']); $this->curl->set(CURLOPT_POSTFIELDS, $postData); $this->curl->set(CURLOPT_HEADER, 1); $this->curl->set(CURLOPT_NOBODY, 0); $this->curl->set(CURLOPT_RETURNTRANSFER, 1); $return = $this->curl->clearCookie()->exec(); if(strstr($return, 'OK|')) { preg_match('/OK\|(.*)/', $return, $resp); $this->captchaID = $resp[1]; return 1; }else{ $this->error = (isset($this->codes['in'][$return]))? $this->codes['in'][$return] : 'cant send'; return 0; } } public function save($name) { if($this->captchaBody) { file_put_contents($name, $this->captchaBody); return 1; }else return 0; } public function load($captcha) { $this->captchaBody = file_get_contents($captcha); return !!$this->captchaBody; } public function recognize() { $tries = 5; while($tries--) { $postData = array( 'key' => $this->acKey, 'action' => 'get', 'id' => $this->captchaID ); $this->curl->rst(); $this->curl->set(CURLOPT_URL, $this->url['getinfo']); $this->curl->set(CURLOPT_POSTFIELDS, $postData); $this->curl->set(CURLOPT_HEADER, 1); $this->curl->set(CURLOPT_RETURNTRANSFER, 1); $this->curl->set(CURLOPT_NOBODY, 0); $this->curl->set(CURLOPT_FOLLOWLOCATION, 1); $return = $this->curl->clearCookie()->exec(); if(strstr($return, 'OK|')) { preg_match('/OK\|(.*)/', $return, $resp); return $resp[1]; }else{ sleep($this->timeOut); } } } public function simple($first, $second = '') { $res = (stristr($first, 'http://'))? $this->get($first, $second) : $this->load($first); if($res && $this->send()) return $this->recognize(); } } В данном случае работу с aquacurl я описывать не буду, там всё интуитивно понятно Приведу примеры распознавания капчи с помощью ac-service.info (AntiCaptcha) PHP: //убираем лимит, включаем ошибки, инклудим библиотеку set_time_limit(0); error_reporting(7); include('ascript.php'); // url до капчи, куки (опционально), ключ антикапчи (брать на сайте сервиса) $url = 'http://vkontakte.ru/captcha.php?s=1&sid=248439795815'; $cookie = 'куки'; $acKey = 'abd6*******426'; // инициализируем класс работы с курл $curl = new aquacurl; // инициализируем класс работы с антикапчей // передаём ей ключ, задержку в секундах при проверке результата распознания // капчи на сервисе, формат капчи, ссылку на созданный класс работы с curl $ac = new anticaptcha($acKey, 5, 'jpg', &$curl); // ================ МЕТОД 1 ПРОСТОЙ // передали урл и куки (опционально) - получили код капчи $key = $ac->simple($url, $cookie); // либо передали имя файла (ну и путь если надо) $key = $ac->simple('captcha.jpg'); // ================ МЕТОД 2 РАСШИРЕННЫЙ // грузим капчу с урла (+ куки) $ac->get($url, $cookie); // если удалось отправить if($ac->send()) { // распознаем $key = $ac->recognize(); // заодно смотрим ошибки $error = $ac->error; } // если капча уже есть в файле, то грузим из файла $ac->load('captcha.jpg'); // а потом отправляем и распознаем // если надо сохрнить капчу - указываем имя файла $ac->save('captcha.jpg'); Вот и всё Надеюсь код окажется кому-либо полезным, в любом случае я жду конструктивной критики и замечаний.