login:        password:      
Combats Scrolls
Rambler's Top100
Гость БК
ru
updated 24.03.09 02:05
24-03-09 @ 01:59

developers Open info : Damnedest Open user info Open user photogallery
Получаем инфу из БК
Давным давно  Alex Nomad [9] рассказывал о том, как правильно получать информацию о персонаже в и приводил пример обращения к страницам БК. Мне кажется, что уже давным давно пора начинать использовать ООП, котрое есть в пыхе и использовать православные методы.

Собственно преимущества кода, который я предлагаю:
1. Мы ограничиваем максимальное количество редиректов тремя. Это не даст возможность серверу БК зациклить наш скрипт.
2. Мы ограничиваем время доступа к странице 10 секундами (хотя даже 10 много, лучше 3-5), чтобы не тратить много времени на тормозящий сервер БК.
3. Получением данных занимается curl (редиректы, таймауты, правильное разархивация)
4. В результате работы, с помощью iconv, мы получаем нормальную UTF-8 строчку, с которой можем спокойно работать. Забудьте вы уже о win-1251 - это архаизм! Надо смотреть в будущее.
5. Ну и собственно мы получаем очень хорошие исключение на все ошибки, которые возникнут во время получения данных, которые можно будет отловить и как-то обработать.

Код модуля можно посмотреть под катом. Появившиеся вопросы можно оставить в комментах.

<?

/**
.* Класс утилит для работы с БК
.*
.* @version 0.1
.* @author Eugene Reich <eugene.reich@gmail.com>
.*/

class CombatsUtils
{
..../**
.... * Возвращает содержимое страницы в UTF-8 кодировке
.... * Метод анализирует возвращаемые результаты и кидает соответствующие исключения
.... *
.... * @param string $url
.... * @static
.... * @access public
.... * @return string
.... */
....
....static public function getUrl($url)
....{
........$ch = curl_init();
........
........curl_setopt($ch, CURLOPT_URL, $url);
........curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
........curl_setopt($ch, CURLOPT_HEADER, 0);
........curl_setopt($ch, CURLOPT_TIMEOUT, 10);
........curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
........curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
........curl_setopt($ch, CURLOPT_FAILONERROR, true);
........curl_setopt($ch, CURLOPT_ENCODING, 'gzip');

........$result = curl_exec($ch);
........$error = curl_error($ch);
........$error_no = curl_errno($ch);
........
........if ($error_no)
........{
............if ($error_no == 47)
...............throw new CombatsUtilsExceptionMaxRedirects();

............if ($error_no == 28)
................throw new CombatsUtilsExceptionTimeout();

............if ($error_no == 7)
................throw new CombatsUtilsExceptionConnection();

............if ($error_no == 52)
................throw new CombatsUtilsExceptionEmpty();

............throw new CombatsUtilsExceptionCurl($error_no.':'.$error);
........}

........// Меняем кодировку
........return iconv('windows-1251', 'utf-8', $result);
....}
}

/**
.* Базовый класс исключений
.*
.* @uses NException
.* @version 0.1
.* @author Eugene Reich <eugene.reich@gmail.com>
.*/

class CombatsUtilsException extends Exception {}

/**
.* Превышено максимально допустимое количество редиректов
.*
.* @uses CombatsUtilsException
.* @version 0.1
.* @author Eugene Reich <eugene.reich@gmail.com>
.*/

class CombatsUtilsExceptionMaxRedirects extends CombatsUtilsException {}

/**
.* Превышен таймаут ожидания ответа от сервера
.*
.* @uses CombatsUtilsException
.* @version 0.1
.* @author Eugene Reich <eugene.reich@gmail.com>
.*/

class CombatsUtilsExceptionTimeout extends CombatsUtilsException {}

/**
.* Не удалось установить соединение с сервером
.*
.* @uses CombatsUtilsException
.* @version 0.1
.* @author Eugene Reich <eugene.reich@gmail.com>
.*/

class CombatsUtilsExceptionConnection extends CombatsUtilsException {}

/**
.* Пришел пустой ответ
.*
.* @uses CombatsUtilsException
.* @version 0.1
.* @author Eugene Reich <eugene.reich@gmail.com>
.*/

class CombatsUtilsExceptionEmpty extends CombatsUtilsException {}

/**
.* Непредусмотренное исключение
.*
.* @uses CombatsUtilsException
.* @version 0.1
.* @author Eugene Reich <eugene.reich@gmail.com>
.*/

class CombatsUtilsExceptionCurl extends CombatsUtilsException {}

Я думаю, что это: Scrolls.multiLike:)

view mode: linear threads
Total disscussion threads: 8 Pages: 1
«« « 1 » »»

Post reply | Post reply with quote
Гость БК
24-03-09 @ 11:03
copy link to clipboard
Следует добавить что данный код будет работать только в PHP версии 5.0 и выше.
Начинание очень хорошее!
Предвижу что в скором будущем автор захочет опубликовать код работы бота. По этому поводу хотелось бы предостеречь ибо это может привести к появлению огромного количества клановых сервисов с флудящими запросами к серверам БК. Предлагаю к таким публикациям относится очень осторожно, ибо судя по тем вопросам что мне иногда задают "клановые программисты" иногда волосы дыбом встают.
Post reply Ответить с цитированием
Язон Дин Альт Open user info
24-03-09 @ 11:29
Re:
copy link to clipboard
а смысл пхп ниже 4ого? для "православного" проекта это уже моветон))
Post reply Ответить с цитированием
Damnedest Open user info Open user photogallery
25-03-09 @ 01:50
Re: Re:
copy link to clipboard
Ога, православие побядит! Пых только 5, причем последней версии )
Post reply Ответить с цитированием
Damnedest Open user info Open user photogallery
25-03-09 @ 01:50
Re:
copy link to clipboard
Полностью с Вами согласен. Выкладывать код бота сюда было бы глупо. Я лишь пытаюсь дать тем, кто хочет что-то сделать для БК в руки правильные функции, чтобы они не писали "быдлокод", а делали сразу правильно и пытались задуматься, почему я поставил указанные цифры и кинул исключения )
Post reply Ответить с цитированием
Damnedest Open user info Open user photogallery
25-03-09 @ 01:56
Re:
copy link to clipboard
И забыл. PHP4 больше не поддерживается. Так что его можно не брать в рассчет.
Post reply Ответить с цитированием
Хранитель Снов Open user info Open user photogallery
02-04-09 @ 13:36
copy link to clipboard
Не плохо для затравки :)
Post reply Ответить с цитированием
l-Michael-l Open user info Open user photogallery
17-04-09 @ 14:54
copy link to clipboard
для чего надо было извращатся с дополнительными классами, чтоб ексепшн показать (!)?

обычно такой скрипт будет работать где-то в "фоне". Лично я бы зделал попроще это...


class CombatsUtils
{
..../**
.... * Возвращает содержимое страницы в UTF-8 кодировке
.... * Метод анализирует возвращаемые результаты и кидает соответствующие исключения
.... *
.... * @param string $url
.... * @static
.... * @access public
.... * @return string
.... */
....
....public static function getUrl($url)
....{
........$ch = curl_init();
........
........curl_setopt($ch, CURLOPT_URL, $url);
........curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
........curl_setopt($ch, CURLOPT_HEADER, 0);
........curl_setopt($ch, CURLOPT_TIMEOUT, 10);
........curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
........curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
........curl_setopt($ch, CURLOPT_FAILONERROR, true);
........curl_setopt($ch, CURLOPT_ENCODING, 'gzip');

........$result = curl_exec($ch);
........$error_no = curl_errno($ch);
........curl_ close($ch);
........// Меняем кодировку
........return empty($error_no) ? iconv('windows-1251', 'utf-8', $result) : null;
....}
}

а после выполнения, просто проверять или вернуло какое-то значение.

да и работать в данном случае будет и в 4й версии


PS. и не надо забывать закрывать коннекшн
Post reply Ответить с цитированием
Гость БК
20-04-09 @ 18:40
copy link to clipboard
Сделано это для следующих вариантов работы:

try
{
Combats::getUrl('http://...');
}
catch(CombatsUtilsException $e)
{
//Выставить флаг о необходимости повторения запроса через 5 минут
}

Также индивидуально можно проставить разное время в разных ситуациях + на мыло можно кидать лог с исключением, узнав когда и какое исключение произошло
Post reply Ответить с цитированием
Гость БК
23-05-09 @ 16:50
Непонятка(
copy link to clipboard
Имею следущий код:

<?
include_once("mysql.php");

class CURL {
var $callback = false;

function setCallback($func_name) {
$this->callback = $func_name;
}

function doRequest($method, $url, $vars) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
//curl_setopt($ch, CURLOPT_URL, $url);
//curl_setopt($ch, CURLOPT_HEADER, 0);
//curl_setopt($ch, CURLOPT_TIMEOUT, 1);
//curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
//curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
//curl_setopt($fh, CURLOPT_REFERER, 'http://knl/');
//curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
//curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
if ($method == 'POST') {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
}
$data = curl_exec($ch);
curl_close($ch);
if ($data) {
if ($this->callback)
{
$callback = $this->callback;
$this->callback = false;
return call_user_func($callback, $data);
} else {
return $data;
}
} else {
return curl_error($ch);
}
}

function get($url) {
return $this->doRequest('GET', $url, 'NULL');
}

function post($url, $vars) {
return $this->doRequest('POST', $url, $vars);
}
}


if (!function_exists('array_combine')) {
function array_combine($a, $b) {
$c = array();
if (is_array($a) && is_array($b))
while (list(, $va) = each($a))
if (list(, $vb) = each($b))
$c[$va] = $vb;
else
break 1;
return $c;
}
}

function doPost($uri,$postdata,$host){
$da = fsockopen($host, 80, $errno, $errstr);
if (!$da) {
echo "$errstr ($errno)<br/>\n";
echo $da;
}
else {
$salida ="POST $uri HTTP/1.1\r\n";
$salida.="Host: $host\r\n";
$salida.="User-Agent: PHP Script\r\n";
$salida.="Content-Type: application/x-www-form-urlencoded\r\n";
$salida.="Content-Length: ".strlen($postdata)."\r\n";
$salida.="Connection: close\r\n\r\n";
$salida.=$postdata;
fwrite($da, $salida);
while (!feof($da))
$response.=fgets($da, 128);
$response=split("\r\n\r\n",$response);
$header=$response[0];
$responsecontent=$response[1];
if(!(strpos($header,"Transfer-Encoding: chunked")===false)){
$aux=split("\r\n",$responsecontent);
for($i=0;$i<count($aux);$i++)
if($i==0 || ($i%2==0))
$aux[$i]="";
$responsecontent=implode("",$aux);
}//if
return chop($responsecontent);
}//else
}//function-doPost

$ar_complete=array();
$ar_keys=array();
$ar_items=array();

function myarray(&$item)
{
global $ar_keys;
global $ar_items;

$tmp_ar=split("=",$item);
$ar_keys[]=$tmp_ar[0];
$ar_items[]=$tmp_ar[1];
}

function print_rf($str)
{
echo("<pre>");
print_r($str);
echo("</pre>");
}

$result = mysql_query ("SELECT login,gamecity_url FROM ".ST_TABLE, $LINK) or die("index.php -> err ".mysql_error($LINK));

if ($row->gamecity=="")
{
$gamecity="http://emeraldscity.combats.com";
} else {
$gamecity=$row->gamecity_url;
}

$curl=new CURL;

for ($i = 0; $i < mysql_num_rows ($result); $i++) {
$row = mysql_fetch_object ($result);
//$url=$gamecity."/inf.pl?login=".$row->login."&short=1";
//$p_url=parse_url($gamecity);

$contents=$curl->post($gamecity."/inf.pl","login=".$row->login."&short=1");

//$contents = @doPost("/inf.pl","login=".$row->login."&short=1",$p_url[host]);
if (stristr($contents,"[503]")) break;
if (stristr($contents,"The document has moved")) {
sleep(1);
$host=stristr($contents,"http://");
$host=str_replace("\n","",$host);
$host=str_replace("\r","",$host);
$host=str_replace(" ","",$host);
$pos = strpos($host, '"', 1);
$url=substr($host, 0, $pos);
$p_url=parse_url($url);
$contents =$curl->post("http://".$p_url[host]."/inf.pl","login=".$row->login."&short=1");
//$contents = @doPost("/inf.pl","login=".$row->login."&short=1",$p_url[host]);
}

$ar=$ar_complete=$ar_keys=$ar_items=array();
$ar=split("\n",$contents);
array_walk($ar,'myarray');
$ar_complete = array_combine ( $ar_keys, $ar_items );

$login=$row->login;
if (!array_key_exists("login_online", $ar_complete)) {
mysql_query ("UPDATE `".ST_TABLE."` SET login_online='0' WHERE login='$login'") or die("update.php -> err ".mysql_error($LINK)."\n");
mysql_query ("UPDATE `".ST_TABLE."` SET room_name='' WHERE login='$login'") or die("update.php -> err ".mysql_error($LINK))."\n";
}
foreach ($ar_complete as $key => $value) {
//print_rf($ar_complete);
//echo("UPDATE ".ST_TABLE." SET ".$key."='".$value."' WHERE login='$login'");
//exit;
if (($row->key)!=$value) {
//print_rf($row->$key);
// print_rf($value);
// print_rf ("UPDATE ".ST_TABLE." SET ".$key."=".$value." WHERE login=".$login."\n");
mysql_query ("UPDATE `".ST_TABLE."` SET ".$key."='".$value."' WHERE login='".$login."'") or die("update.php -> err ".mysql_error($LINK)."\n");
//exit;
}
}
sleep (1);
}
mysql_free_result ($result);
?>

Обновляется 14 человек из 30 членов клана... Постоянно выдаёт:

Fatal error: Maximum execution time of 30 seconds exceeded in W:\home\knl\www\update.php on line 181

Гуру, помогие:)
Post reply Ответить с цитированием
Гость БК
26-05-09 @ 19:00
copy link to clipboard
set_time_limit(0); И все станет норм.
sleep лучше сделать в 3 секунды.
Post reply Ответить с цитированием
Vikis
26-05-09 @ 20:38
непонятка
copy link to clipboard
Спасибо,всё работает:) Курл стал выдавать ошибки.... НО это уже мелочи. Видимо из-за кодировки win-1251
Post reply Ответить с цитированием
Damnedest Open user info Open user photogallery
28-05-09 @ 17:55
copy link to clipboard
Это хорошо )
Post reply Ответить с цитированием

Post reply | Post reply with quote

Total disscussion threads: 8 Pages: 1
«« « 1 » »»


 
 © 2007–2024 «combats.com»
  18+  
feedback