Пишем бота для браузерной игры при помощи cURL (PHP)
Играли ли вы когда нибудь в браузерную игру? А часто ли вы наблюдали, что разработчики игр часто ставят пользователей в такую ситуацию, когда "прокачка" вашего чара (персонажа) становится настолько уныла, что для того, чтобы ускорить этот процесс вам предлогают платить реальные деньги, за получение всяких плюшек. Цель разработчиков игры - максимальная прибыль с "хомячков", которые "клюнули на крючок". Те, у кого толстые кошельки, платят денюжку и радуются жизни. Другие, т.н "задроты" или "школота" упорно не сдаются и продолжают тупо монотонно зарабатывать игровые деньги или другие игровые ресурсы. Но эти два способа нам не подходят! Потому что игра то в браузере! И все действия проходят по стандартному HTTP протоколу, создавая от пользователя GET или POST запросы. Поэтому-то мы и напишем бота, который будет висеть в кроне (планировщик задач) и добывать ценные игровые ресурсы за нас
Для этой цели нам хорошо подойдет библиотека cURL в PHP. Итак, приступим.
Для тех, кто незнаком с cURL (Client URL Library), объясню как происходит работа:
Инициализируем новую сессию через функцию curl_init
Навешиваем кучу опций для нашего дальнешего запроса к серверу, через curl_setopt или curl_setopt_array
Выполняем сформированный запрос через curl_exec
Получаем ответ, обрабатываем данные, меняем опции cURL-сессии, снова выполняем, итд.
CURL — это удобная библиотека, позволяющая автоматически логинится на сайте, сохранять данные сессии (куки) в файл с последующем их использованием, автоматически следовать по ссылке при серверном редиректе (301, 302), автоматически подставлять реферер страницы, итд.
Итак, напишем класс, который будет создавать новую CURL сессию, и будет иметь метод, позволяющий менять основные опции в рамках одной CURL-сессии, чтобы управлять процессом грабинга страницы
Это будут в основном 2 параметра: метод запроса страницы (GET или POST) и данные для отправки (для POST-а).
Вот список основных опций для curl_setopt, которые нам понадобятся:
CURLOPT_HTTPHEADER - опция нужна для формирования дополнительных заголовков в HEAD, отправляемых серверу. она будет нужна в основном для эмуляции захода пользователя "через браузер".
CURLOPT_COOKIEFILE - абсолютный путь до файла куков (путь для сохранения)
CURLOPT_COOKIEJAR - абсолютный путь до файла куков (путь использования уже созданного файла, должен быть такой же как и CURLOPT_COOKIEFILE)
CURLOPT_AUTOREFERER - с этой опцией cURL будет автоматически подменять заголовок HTTP_REFERER при всяких редиректах
CURLOPT_RETURNTRANSFER - включение этой опции отключает автоматически вывод результата в браузер (print, echo) после curl_exec, таким образом он будет возвращатся нам через return.
CURLOPT_FOLLOWLOCATION - автоматическое следование при редиректах (301). внимание: эта опция не работает при включенном безопасном режиме safe_mode или установленном значении open_basedir, до php 5.3 эти опции можно отключить только или в php.ini или в httpd.conf файлах
CURLOPT_URL - задаем адрес для последующего вызова curl_exec
CURLOPT_POST - флаг, отвечающий за то, будет ли следующее выполнение curl_exec идти методом POST.
CURLOPT_POSTFIELDS - данные для отправки методом POST в формате param1=value1¶m2=value2
CURLOPT_REFERER - опция для установки Referer-заголовка (для тех кто в танке, это URL-страницы с которой мы пришли на текущую)
Вот, впринципе и всё:
class MyOnlineBrowserGameBot
{
private $user, $pass, $cookie;
public
$url, $referer, $connect,
$html, $xml, $error, $info;
public function __construct($user, $pass)
{
$this->url = 'http://www.адрес-онлайн-игры.ru/';
$this->connect = curl_init();
$this->user = $user;
$this->pass = $pass;
$this->cookie = getcwd() ."/cookie.txt";
$header = explode("\n", trim('
User-Agent: Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.7.62 Version/11.00
Host:
[Вы должны быть зарегистрированы и подключены, чтобы видеть эту ссылку] Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
Connection: Keep-Alive, TE
TE: deflate, gzip, chunked, identity, trailers
'));
array_walk($header, create_function('&$header', '$header = trim($header);'));
curl_setopt_array($this->connect, array
(
CURLOPT_HTTPHEADER => $header,
CURLOPT_COOKIEFILE => $this->cookie,
CURLOPT_COOKIEJAR => $this->cookie,
CURLOPT_AUTOREFERER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true
));
}
public function __destruct()
{
curl_close($this->connect);
}
/** Делаем запрос и меняем реферер **/
protected function action( $params = array() )
{
$ch = $this->connect;
$params = (array) $params;
$timeout = isset($params['timeout']) ? $params['timeout'] : mt_rand(1,3); // sec
$action = $this->url . ($params[0] ? $params[0] : $params['action']);
$method = strtoupper( isset($params['method']) ? $params['method'] : 'GET' );
$postdata = $params['data'];
curl_setopt($ch, CURLOPT_URL, $action);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
switch( $method )
{
case 'GET': {
curl_setopt($this->connect, CURLOPT_HTTPGET, true);
break;
}
case 'POST': {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
break;
}
}
$this->html = curl_exec($ch);
$this->error = curl_error($ch);
$this->info = curl_getinfo($ch);
// получаем DOM страницы для поиска элементов
if( $this->html )
{
@$this->xml = new DomDocument;
@$this->xml->loadHTML( $this->html );
@$this->xpath = new DomXPath( $this->xml );
/* тут также можно получить и сохранить некоторые параметры игры (например количество денег персонажа) */
// пример:
$this->money = $this->xpath->query('//div[@id="money"]/span[@class="count"]')->item(0)->nodeValue;
}
curl_setopt($ch, CURLOPT_REFERER, $this->info['url']); // выставляем реферер после exec
sleep($timeout); // делаем задержку в секундах между запросами
return $this;
}
/** Первый заход на страницу, если файл куков еще не существует логинемся через POST **/
public function login()
{
if( ! realpath($this->cookie) ) // файл еще не создан, логинемся
{
$params = array(
'method' => 'POST',
'data' => 'user='. $this->user .'&password='. $this->pass .'&remember=1'
);
}
$this->action($params);
return $this;
}
}
Основа класса уже готова. Остается только дописать еще игровые методы для конкретной игры, симулирующие "хождение" по сайту и игровой процесс. Также отмечу то, что после того, как мы получили ответ от сервера (данные страницы), нам конечно-же нужно из этой страницы что-то получить. Для этой цели идеально подходят стандартные классы PHP 5 для работы с DOM (Document Object Model) - DomDocument и DomXPath. Для тех кто мало знаком с xpath, можно почитать основную информацию на википедии.
После того, как вы дополните класс методами для конкретной игры, то следующим этапом будет создание файла с режимом работы бота, на основне написанного класса, который в последствии будет вызываться на нашем хостинге планировщиком задач (cron) в нужные нам промежутки времени. Солдат спит, служба идет..
By ГеЙмЕр-ЗаДрОт