Записи

myminicity

1 год назад (2008/08/04 04:43:31)

В сети есть сайт myminicity.com, где каждому желающему предлагают построиьт свой город. Суть заключается в том, чтобы заходить по ссылкам в город увеличивая соответсвующий параметр. Всё просто и лаконично, если не считать, что каждый город можно увеличить 1 раз в сутки с 1-го IP адреса.

Можно, конечно, постоянно отключать интернет и подключать его снова, но это время и силы.

Предлагаю вашему внимания функцию загрузки страницы города, определения следующего необходимого параметра и подготовке к следующему вызову.

Текст функции

В скрипте использовано:

  • Функция writelog($text); Записывающая в файл $log текст переданный в неё и выводящий его же в браузер. (Напишете сами?)
  • Класс html - предназначенны для отрезания от текста частей текста с заданного начала или извлечения до указанных символов. (При необходимости поделюсь.)
  • Функция http_req - Запрашивающая переданную ей страницу с приведёнными параметрами запроса. (При необходимости поделюсь.)

Вызов осуществляется с передачей имени города в качесте единственного аргумента: UpdateCity('megatron.ws');

В качестве домашнего задания написания функции переподключения интернета для смены IP адреса.

html парсер. Часть третья. Разбор текста.

2 года назад (2007/11/25 19:11:19)

Наверное самая большая часть кода и самая важная тут.

	function Parse($text){

$text=preg_replace($this->ReplaceTagsFrom,$this->ReplaceTagsTo,$text);

@preg_match_all('/([^\<]*?)\<(\/?)([^\s]+?)((?:(?:\s+(?:[\w]+?)=("|\')(?:[^\5]*?)(?<!\\\\)\5)*?)(?:\s*)\/?)\>/',$text.'<br />',$textdrop);
$tags=array();
if(count($textdrop[0])==0)
return htmlspecialchars($text);
foreach($textdrop[0] as $id=>$line){
$pretext=$textdrop[1][$id];
$closetag=$textdrop[2][$id]=='/';
$curtag=strtolower($textdrop[3][$id]);
$tagparam=$textdrop[4][$id];
if ($closetag){
// TagClose
if ((count($tags)>0)&&($tags[0]==$curtag)){
$newtext.=htmlspecialchars($pretext).'</'.$curtag.'>';
array_shift($tags);
continue;
}else{
$newtext.=htmlspecialchars($pretext).'&lt;/'.$curtag.'&gt;';
continue;
}
}
elseif (!isset($this->allow[$curtag])){
}else{
// TagOpen
preg_match_all('/\s([\w]+?)=("|\')((?:[^\2]*?)(?<!\\\\))\2/',$tagparam,$params);
$param='';
foreach($params[0] as $pid=>$line){
if (in_array(strtolower($params[1][$pid]),$this->allow[$curtag]))
if (strtolower($params[1][$pid])=='href'){
// Провека ссылок
preg_match('/(?:(\w*?):)(.*)/',$params[3][$pid],$link);
if ((count($link)==0)||(in_array(strtolower($link[1]),$this->AllowProtocols)))
$param.= ' '.$params[1][$pid].'='.$params[2][$pid].$params[3][$pid].$params[2][$pid];
}else
$param.= ' '.$params[1][$pid].'='.$params[2][$pid].$params[3][$pid].$params[2][$pid];


}
if (in_array($curtag,array_keys($this->allow))){
if (!in_array($curtag,$this->simpletag)){
array_unshift($tags,$curtag);
$newtext.=htmlspecialchars($pretext).'<'.$curtag.$param.'>';
}else{
$newtext.=htmlspecialchars($pretext).'<'.$curtag.$param.' />';
}
continue;
}
}

 


$newtext.=htmlspecialchars($pretext).'<'.($closetag?'/':'').$curtag.htmlspecialchars($tagparam).'>';

}
foreach($tags as $tag)
$newtext.='</'.$tag.'>';

return $newtext;
}

Если рассматривать работу данного скрипта по порядку, то:

  1. Сначала производится замена тегов согласно правил замены.
  2. Происходит разбор всего текста с помощью регулярного выражения. Получилось немного громоздкое, но работоспособное.
  3. Проверка количства найденых тегов, и если почему-то ничего не нашлось, то вывод текста, всё равно с экранированием лишнего, вдруг обошли регулярку.
  4. Начинается цикл по всем найденным тегам, вот и началось всё инетересное.
    1. В начале может быть странный текст не относящийся к тегам.
    2. Проверям наличие / в началетега, тем самым определяем что происходит.
    3. Вытаскиваем имя тега и его параметры.
    4. Если тег закрывается, то мы проверям допустимость закрытия его, то есть, что он был открыт последним или просто отображаем его на экране, как текст.
    5. Если тег не закрывался, то надо проверить, может ли он открываться и если может, то
      1. Производим разбор всех параметров у тега в массив.
      2. Проходим по массиву параметров и проверям доступность их применения их у тега.
      3. Если параметр является ссылкой, то ещё дополнительно разбираем её отделяя протокол если передан.
      4. Проверив протокол на правильность мы записываем параметр к тегу.
      5. Если тег может открываться, хмм... Ну ладно два раза не будет лишним проверить.
      6. В зависимости отприменения тега одиночным или нет, мы добавим в стек тегов его или нет и также занесём в код.
    6. Если мы таки не нашли что делать нам с тегом, то выведем его как есть на экран.
  5. Остаётся пробежаться по всем не закрытым тегам и закрыть их.

Вот и готов текст.

html парсер. Часть вторая, инициализация

2 года назад (2007/11/25 18:36:49)

Продолжив колдовать и создав несколько функций инициализации, мы получаем следующую картину.

function ClearAllow(){
$this->allow=array();
}

function InitAllow(){
$this->SetAllow(array(
'a' => array('href','target','style','class'),
'img' => array('src','border','alt','title','style','class','width','height','align'),
'br' => array('style','clear','class'),
'hr' => array('style','clear','class'),
'span' => array('style','class'),
'div' => array('style','class'),
'p' => array('style','title','class'),
'ul' => array('style','class'),
'li' => array('style','class'),
'ol' => array('style','class'),
'sup' => array('style','class'),
'sub' => array('style','class'),
'b' => array('style','class'),
'i' => array('style','class'),
'u' => array('style','class'),
's' => array('style','class'),
'em' => array('style','class'),
'strong' => array('style','class'),
'center' => array('style','class'),
'form' => array('style','class','action','method','target'),
'h1' => array('style','class'),
'h2' => array('style','class'),
'h3' => array('style','class'),
'h4' => array('style','class'),
'h5' => array('style','class'),
'h6' => array('style','class'),
'input' => array('type','value','name','style','class','readonly','disabled'),
'label' => array('style','class'),
'object' => array('classid','codebase','width','height'),
'param' => array('name','value'),
'embed' => array('type','height','width','wmode','src','flashvars'),
'table' => array('class','style','cellpadding','cellspacing','border','id'),
'tr' => array('class','style','id'),
'th' => array('class','style','id'),
'td' => array('class','style','col'),
'pre' => array('class','style','id'),
));
//
}

 

function AddReplace($from,$to){
$this->ReplaceTagsFrom[] =$from;
$this->ReplaceTagsTo[] =$to;
}

function SetAllow($array){
$this->allow=$array;
}

Рассмотрим функции подробнее:

ClearAllow - Является своего рода функцией инициализации, которая просто очищает список доступных тегов, тоесть воспользовался ей и ни один кусок кода не пройдёт.

InitAllow - Создаёт массив, в котором ключами являются допустимые теги, а значениями - допустимые параметры у этих тегов. Приведённый выше пример, достаточен, для большеого числа HTML кода.

AddReplace - Необходима, только для правильного заполения массива замен тегов. Один из важных это замена тега <lj user=""> и в будующей тега используемого на маил.ру. 

SetAllow - Применятеся для установки смассива замен созданного в функции инициализации. 

Что может потребоваться в дальнейшем: Функции отключения каких-то замен, на время работы парсера. Также функции добавления и удаления отдельных тегов и параметров тегов.

В третьей части будет рассотрена логика и сам парсер. 

И так какое-то подобие html парсера. Часть первая, подготовка.

2 года назад (2007/11/25 18:24:35)

Для начала, нам неплохо было бы и подготовить парсер к обработке.

 

if (!class_exists('HtmlParser')){
class HtmlParser{

var $allow;
var $simpletag;
var $AllowProtocols;
var $ReplaceTagsFrom, $ReplaceTagsTo;

function HtmlParser(){
$this->ClearAllow();
$this->simpletag=array('img','br','hr','input','param');
$this->AllowProtocols=array('http','ftp','skype','about','https');
$this->ReplaceTagsFrom=array();
$this->ReplaceTagsTo=array();
$this->AddReplace('/\<(\/?)b(\s[^\>]*?)\>/i','<$1strong$2>');
$this->AddReplace('/\/i','<span class="lj_user"><a href="http://www.livejournal.com/userinfo.bml?user=$2" title="$2 profile"><img src="http://stat.livejournal.com/img/userinfo.gif" border="0" alt="[info]" /></a><a href="http://$2.livejournal.com/">$2</a></span>');
$this->InitAllow();
}
}

Это пока только заготовка, в неё нету даже реализации всех функций кроме конструктора. Но в планах:

  • Нормальная обработка одиночных тегов.
  • Обработка закрытых двойных закрытых тегов.
  • Допуск разных протоколов в ссылках.
  • Автозамена некоторых тегов, для отображения на экране.
В следующей части рассмотрим функции инициализации.
Авторизация


Поиск на сайте