Logo    
Деловая газета CitCity.ru CITKIT.ru - все об Open Source Форумы Все публикации Учебный центр Курилка
CitForum    CITForum на CD    Подписка на новости портала Море(!) аналитической информации! :: CITFORUM.RU
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

27.04.2017

Google
WWW CITForum.ru
С Новым годом!

Пример использования модулей LWP и HTML::Tree

Дмитрий Николаев, http://perl.dp.ua

В статье речь пойдёт об использовании модулей LWP и HTML::Tree, причём сделано это будет на реальном примере, работу которого Вы можете посмотреть здесь: http://perl.dp.ua/cgi-bin/book.cgi.

Сама идея написать скриптик http://perl.dp.ua/cgi-bin/book.cgi - возникла после того, как встал вопрос о том, что раздел "книги" сайта http://perl.dp.ua - надоело дополнять/редактировать и т.д. вручную. Захотелось это дело автоматизировать, сделать поиск и т.д. Первая идея, которая возникла, - это было создание мини интернет-магазина, куда вносились бы книги и т.д. Но, это опять таки требовало присутствия человека. И тогда, я подумал, а почему бы не сделать скриптик, который бы скачивал нужную страницу с Озона, парсил бы её, как мне надо, и передавал бы броузеру. Методом решения стали модули(пакеты модулей :)) LWP и HTML::Tree.

В данный момент скрипт выполняет следующее: при запросе - "смотрит в свой кэш" и в случае, если ничего там не находит, то производит скачивание нужной страницы с Озона, парсинг её и складирование в кэш + вывод броузеру... Естественно, при парсинге меняются некоторые ссылки, в частности ссылки перехода на следующую страницу результатов поиска и т.д.

Итак, давайте приступим к разбору кода:

1    #!/usr/bin/perl

2    use strict;

# далее грузим модули, которые нам понадобятся
3    use LWP;
4    use CGI;
5    use CGI::Carp qw(fatalsToBrowser);
6    use HTML::TreeBuilder;
7    use Lingua::DetectCharset;
8    use Convert::Cyrillic;
9    use URI::Escape;

10   my $flock_allow=1; # рарешать ли блокировку файлов

11   my $mainhost='http://perl.dp.ua'; # Ваш хост...
12   my $books_cache_dir = 'dir_for_cache'; # директория, в которой будут хранится кэшированные файлы
13   my $coi = new CGI;

14   print $coi->header(); # выводим заголовки

15   if(!(-d "./$books_cache_dir")){ # проверяем существование директории для кэш-файлов
16    system("/bin/mkdir", "-m", "0777", "$books_cache_dir"); #Unix
17    system("mkdir", "$books_cache_dir"); #Windows
18   }

19   my $phrase= uri_escape($coi->param('text')); # получаем запрос, по которому ведётся поиск, переводим всё в escape последовательности
20   $phrase = 'perl' unless $phrase or $coi->param('path'); # по умолчанию - запрос 'perl', остальное - для совметимости со старой версией скрипта,поисковики о ней ещё помнят :)

21   my $path;
22   my $page_num;

23   if($coi->param('page')){ # определяем номер текущей страницы для отображения( в Озоне, если количество книг > 20, то происходит разбивка книг по 20 на страницу)
24    $page_num = int($coi->param('page'));
25    $page_num = 0 if $page_num<0;
26  }
27  if($page_num){ # вычисляем, какую страницу на нужно качать
28    $path = 'http://www.ozon.ru/?context=advsearch_book&partner=d392&title=' .$phrase.'&page='.$page_num;
29  }
30  else{
31   unless($coi->param('path')){
32     $path = 'http://www.ozon.ru/?context=advsearch_book&partner=d392&title='.$phrase;
33   }
34   else{
35     my $add_path = uri_unescape($coi->param('path'));
36     $path = 'http://www.ozon.ru'.$add_path."&partner=d392";
37     if($add_path =~m /title=(.*)&/i){$phrase=$1;}
38   }
39  }

40   open(cache_list,"$books_cache_dir/list.cache"); # "смотрим на текущее состояние кэша"
41   if ($flock_allow){lockfile('cache_list');} # если разрешено блокирование файла, то блокируем
42   my @cache=<cache_list>; #cause the number of searches is small
43   if ($flock_allow){unlockfile('cache_list');} # соответственно - разблокируем
44   close(cache_list);

46   my $cache_time = 604800; # делаем время обновление кэша равным 1-ой неделе
47   my $page = undef;

48   for(my $i=0; $i<=$#cache; $i++){ # перебераем кэш и пытаемся найти нужный файл
49    my $line=$cache[$i];
50    chomp $line;
51    my @temp_cache= split /%unreal_delimiter%/, $line; # разбираем потихоньку информацию

52    if(($temp_cache[1] eq $path)and((int(time())-int($temp_cache[0]))<$cache_time)){ # в случае, если кэш - не старый, то берём его и далее работаем с ним
53     open(cache, '$books_cache_dir/'.$temp_cache[0].'.cache');
54     if ($flock_allow){lockfile('cache');}
55     undef $/;
56     $page=<cache>;
57     $/="\n";
58     if ($flock_allow){unlockfile('cache');}
59     close(cache);
60     last;
61    }
62    elsif($temp_cache[1] eq $path){ # в противном случае обновляем этот кэш
63     my $browser = LWP::UserAgent->new(); # Качаем страницу
64     my $response = $browser->get($path,
65         'User-Agent' => 'Mozilla/4.76 [en] (Win98; U)',
66         'Accept' => 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*',
67         'Accept-Charset' => 'iso-8859-1,*,utf-8',
68         'Accept-Language' => 'en-US',
69         ); # Прикидываемся броузером
70     $page = razbor($response->content, $phrase); # razbor - это функция парсинга страницы с Озона, см. ниже
71     while (-e '$books_cache_dir/'.time().'.cache') { sleep(2); } #в случае, если файл существует(два пользовтеля одновременно запросили обновление или добавление), то немного "спим"
72     my $temp_time = time();
73     open(cache, ">$books_cache_dir/".$temp_time.'.cache'); # сохраняем информацию в файл
74     if ($flock_allow){lockfile('cache');}
75     print cache $page;
76     if ($flock_allow){unlockfile('cache');}
77     close(cache);
78     $cache[$i] = join('%unreal_delimiter%',$temp_time,$path, $coi->param('text'))."\n"; unlink($books_cache_dir.'/'.$temp_cache[0].'.cache'); # обновляем информацию, удаляем старый кэш

79     open(cache_list,">$books_cache_dir/list.cache"); # сохраняем список сохранённых страниц
80     if ($flock_allow){lockfile('cache_list');}
81     foreach my $string(@cache){
82      print cache_list $string;
83     }
84     if ($flock_allow){unlockfile('cache_list');}
85     close(cache_list);
86     last;
87    }
88   }

89   unless($page){ # производим новое добавление страницы, которая ранее известна скрипту не была
# Очень всё похоже на вышеописанный процесс обновления кэша, поэтому комментарии здесь излишни
90    my $browser = LWP::UserAgent->new();
91    my $response = $browser->get($path,
92       'User-Agent' => 'Mozilla/4.76 [en] (Win98; U)',
93       'Accept' => 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*',
94       'Accept-Charset' => 'iso-8859-1,*,utf-8',
95       'Accept-Language' => 'en-US',
96        );

97    $page = razbor($response->content, $phrase);

98    while (-e '$books_cache_dir/'.time().'.cache') { sleep(2); }

99    my $temp_time = time();

100   open(cache, ">$books_cache_dir/".$temp_time.'.cache');
101   if ($flock_allow){lockfile('cache');}
102   print cache $page;
103   if ($flock_allow){unlockfile('cache');}
104   close(cache);

105   my $new_cache_string = join('%unreal_delimiter%',$temp_time,$path)."\n";

106   open(cache_list,">>$books_cache_dir/list.cache");
107   if ($flock_allow){lockfile('cache_list');}
108   print cache_list $new_cache_string;
109   if ($flock_allow){unlockfile('cache_list');}
110   close(cache_list);
111  }

112  $phrase = uri_unescape($phrase); # преобразуем escape-последовательности к нормальному виду

113  print "<center><form style='margin: 0.1px' action='book.cgi' method=post><font size=\"2\" face=\"Arial, Helvetica, sans-serif\"><strong>Искать по названию:</strong></font>&nbsp;<input type=text name=text value='$phrase' size=30><input type=submit value='Искать'></form><br>";

114  print $page;

115  sub razbor(@_){ # функция разбора информации
116     my @arr = @_;
117     my $page = $arr[0]; # получаем содержимое Озоновской страницы
118     my $charset = Lingua::DetectCharset::Detect ($page); # определяем кодировку документа, у Озона она win-1251, но делается это на всякий случай, а вдруг они перейдут на Кои-8 или данные попадают скрипту через какой-нибудь кэш-сервер, который перекодирует документы
119     $page = Convert::Cyrillic::cstocs ($charset, 'win', $page); # преобразуем в кодировку win-1251

120     my $root = HTML::TreeBuilder->new_from_content($page); # создаём объект HTML::TreeBuilder на основании содержания страницы

121     my $text_string2;

122     foreach my $table ($root->look_down(_tag => 'td')){ # ищем столбцы в таблицах и убираем ненужную информацию

123      my $table_html = $table->as_HTML("<>%");
124      if($table_html =~ m%Результаты поиска%ig){
125       $text_string2 = $table_html;
126      }
127     }

128     undef $root;
129     $root = HTML::TreeBuilder->new_from_content($text_string2); # пересоздаём объект на основании исправленных данных

130     my $basic_html = $root->as_HTML("<>%");

131     $basic_html =~ s/#6699cc/#38549C/g; # изменение цвета верхней полосы
132     $basic_html =~ s/#336699/#38549C/g; # изменение цвета верхней полосы
133     $basic_html =~ s/bgcolor="#ffffff"/bgcolor="#F4f4f4"/g; # изменение цвета фона текущей страницы(в ссылках)
134     $basic_html =~ s/bgcolor="White"/bgcolor="#F4f4f4"/ig; # изменение цвета фона страницы
135     $basic_html =~ s%<small class="micro">Книгопечатная продукция</small><br>%%ig; # убираем лишнюю информацию
136     $basic_html =~ s%<big class="BIG2">Результаты поиска</big><br><b><small>Найдено (\d+)</small></b>%%i;
137     $basic_html =~ s%style="padding-top:12;"%%i;

138     undef $root;
139     $root = HTML::TreeBuilder->new_from_content($basic_html);

140     foreach my $a ($root->look_down(_tag => 'a')){ # измененяем ссылки в документе на те, что нам нужно: в случае ссылки на другую страницу - изменяем эту ссылку на ссылку на скрипт; в случае ссылки на книгу подставляем партнёрский идентификатор
141      if($a->attr('href')=~ m/page=(\d+)/){$a->attr('href','http://perl.dp.ua/cgi-bin/book.cgi?text='.$arr[1].'&page='.$1);}
142      else{$a->attr('href','http://ozon.ru'.$a->attr('href')."?partner=d392"); $a->attr('target','_new_'.int(100000*rand()));}
143     }
144     $root->pos(undef);

145     foreach my $img ($root->look_down(_tag => 'img')){ # правим адреса картинок
146      my $temp = $img->attr('src');
147      $temp =~ s%//%/%ig;
148      $img->attr('src','http://ozon.ru'.$temp);
149     }
150     $root->pos(undef);

151     foreach my $td ($root->look_down(_tag => 'td', class => 'salecol')){ # убираем ненужную информацию
152      if($td->as_HTML("<>%") =~ m%buy%){
153       $td->replace_with('&nbsp;');
154      }
155     }
156     $root->pos(undef);

157     foreach my $td($root->look_down(_tag => 'table', cellspacing => '1')){
158      if($td->as_HTML("<>%") =~ m%<small style="color:FFFFFF"><b>(.*)</b>%){
159       $td->replace_with('&nbsp;');
160     }
161    }

162     foreach my $td($root->look_down(_tag => 'table', cellpadding => '3')){
163      if($td->as_HTML("<>%") =~ m%<td class="paddleft"><small style="color:FFFFFF"><b>(.*)</b></small>%){
164       $td->replace_with('&nbsp;');
165      }
166     }

167     $text_string2 = $root->as_HTML("<>%"); # выводим получившуюся изменённую страницу. Если не указать параметров "<>%"- то для русского языка будут проблемы в том, что документ будет непонятно в какой кодировке(по крайне мере в этой версии HTML::Tree), хотя для английского языка будет всё ок, хотя автор модуля рекомендует использовать именно так этот метод для совместимости со старыми версиями модуля.

168     return $text_string2;
169  }

170  sub lockfile # функция блокировки файла
171  {
172     my $handle=shift;
173     my $count = 0;
174     until (flock($handle,2)){
175       sleep . 10;
176       if(++$count > 50){
177        print "<center><h1><font color=red>Sorry, Server is too busy. Please visit later.</font></h1></center>";
178        exit;
179       }
180     }
181  }

182  sub unlockfile # функция разблокировки файла
183  {
184    my $handle=shift;
185    flock($handle,8);
186  }

Итак, вроде с кодом разобрались и нужно отметить, что этот скрипт, кроме его достоинста в том, что он работает и то, что использован как учебный материал, имеет несколько недостатков,.. например то, что, наверное, стоило бы объединить добавление новой страницы и обновление старой в одну функцию, ведь эти две "процедуры" - очень похожи... не очень хорошие игры с пересозданием объектов в функцие "разбора" информации. Также к недостаткам можно отнестито, что сейчас Озон предоставляет доступ к своей базе при помощи XML, и это должно ускорить и упростить работу с Озоном при помощи подобных(отдалённо) скриптов. Остальные баги и недостатки Вы можете обсудить на форуме сайта http://perl.dp.ua

Но в целом, скрипт должен быть полезным для начала работы с парсингом html(xml) файлов.
Также, эта статья доступна по адресу: http://perl.dp.ua/practice/bookcgi.html

С уважением,
Дмитрий Николаев

Размещение рекламы — тел. +7 495 4119920, ICQ 232284597

Подписка на новости IT-портала CITForum.ru
(библиотека, CITKIT.ru, CitCity)

Новые публикации:

24 декабря

CITKIT.ru:

  • Новогодние поздравления
  • Сергей Кузнецов. Цикл Операционные системы: Ностальгия по будущему:

  • Алексей Федорчук. OpenSolaris 2008.11 Release

  • Сергей Голубев:

  • Евгений Чайкин aka StraNNik (Блогометки):

    17 декабря

  • С.Д.Кузнецов. Базы данных. Вводный курс

    10 декабря

    CITKIT.ru:

  • OpenSolaris 2008.11 Release

  • Альтернативные ОС: две грустные истории (С.Кузнецов)
  • Nokia N810 — доведение до ума
  • CitCity:

  • Платформа 2009: заоблачные перспективы Microsoft

    4 декабря

  • Лекция С.Д.Кузнецова Понятие модели данных. Обзор разновидностей моделей данных

    CITKIT.ru:

  • OpenSolaris 2008.11 Release. Первые впечатления

  • Linux vs FreeBSD: продолжим "Священные войны"?

  • Nokia N810 as is

  • Индульгенция для FOSS

  • Друзья СПО'2008

    26 ноября

  • Нечеткое сравнение коллекций: семантический и алгоритмический аспекты

    CitCity:

    CITKIT.ru:

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • 19 ноября

  • Проблемы экономики производства крупных программных продуктов

  • Язык модификации данных формата XML функциональными методами

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Заметки к книге:

  • FreeBSD: монтирование сменных устройств и механизм HAL
  • Текстовый редактор ee

    12 ноября

  • Правило пяти минут двадцать лет спустя, и как флэш-память изменяет правила (Гоц Грейф, перевод: Сергей Кузнецов)

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:
  • OSS в России: взгляд правоведа (В.Житомирский)

  • Новая статья из цикла С.Голубева "Железный марш":

    29 октября

  • О некоторых задачах обратной инженерии

  • Веб-сервисы и Ruby

  • Тестирование web-приложений с помощью Ruby

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

  • PuppyRus Linux - беседа с разработчиком (С.Голубев)

  • Сергей Кузнецов. Заметка не про Linux

    22 октября

  • Обзор методов описания встраиваемой аппаратуры и построения инструментария кросс-разработки

    CITKIT.ru:

  • Сергей Кузнецов. Почему я равнодушен к Linux

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • Что надо иметь
    3. Базовые познания

    CitCity:

  • Управление IT-инфраструктурой на основе продуктов Microsoft

    15 октября

  • Методы бикластеризации для анализа интернет-данных

    CitCity:

  • Разъемы на ноутбуках: что они дают и зачем их так много?
  • AMD Puma и Intel Centrino 2: кто лучше?

    CITKIT.ru:

  • Новый цикл статей С.Голубева
    Железный марш:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    8 октября

  • Автоматизация тестирования web-приложений, основанных на скриптовых языках
  • Опыт применения технологии Azov для тестирования библиотеки Qt3

    Обзоры журнала Computer:

  • SOA с гарантией качества
  • Пикоджоуль ватт бережет
  • ICT и всемирное развитие

    CitCity:

  • Пиррова победа корпорации Microsoft

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Статья из архива:

  • Я живу в FreeBSD (Вадим Колонцов)

    Новые Блогометки:

  • Перекройка шаблона Blogger или N шагов к настоящему
  • Blogger. Comment style
  • Screenie или глянцевый снимок экрана

    2 октября

    CITKIT.ru:

  • Сага о FreeBSD (А. Федорчук)

    Zenwalk: пакет недели

  • Банинг — интеллектуальное развлечение (С.Голубев)

    CitCity:

    25 сентября

  • Клермонтский отчет об исследованиях в области баз данных

    CITKIT.ru:

  • Пользователям просьба не беспокоиться... (В.Попов)

  • Снова про ZFS: диск хорошо, а два лучше
  • Командная оболочка tcsh (А.Федорчук)

    Zenwalk: пакет недели

    17 сентября

  • T2C: технология автоматизированной разработки тестов базовой функциональности программных интерфейсов
  • Технология Azov автоматизации массового создания тестов работоспособности

    CITKIT.ru:

  • FreeBSD: ZFS vs UFS, и обе-две — против всех (А.Федорчук)

    Zenwalk: пакет недели

  • Дачнет — практика без теории (С.Голубев)

    10 сентября

  • За чем следить и чем управлять при работе приложений с Oracle
  • Планировщик заданий в Oracle
    (В.Пржиялковский)

    CITKIT.ru:

  • Microsoft: ответный "боян" (С.Голубев)

  • Причуды симбиоза, или снова "сделай сам" (В.Попов)

  • Файловые системы современного Linux'а: последнее тестирование
  • Zsh. Введение и обзор возможностей
    (А.Федорчук)

    Описания пакетов Zenwalk: Zsh, Thunar, Thunar-bulk-rename, Xfce4-places-plugin, Xfce4-fsguard-plugin

    Блогометки:

  • Google Chrome
  • Лончер для ASUS Eee PC 701

    3 сентября

    CITKIT.ru:

  • Заметки о ядре (А.Федорчук):

    Добавлены описания пакетов Zenwalk: Galculator, Screenshot, Gnumeric, Pidgin

    В дискуссинном клубе:

  • И еще о Википедии и Google Knol

  • Лекция для начинающего линуксоида (С.Голубев)

    26 августа

  • Транзакционная память (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Открыт новый проект Zenwalk: пакет недели

  • Статья Текстовые процессоры и их быстродействие: конец еще одной легенды?

    21 августа

    CITKIT.ru:

  • Почему школам следует использовать только свободные программы (Ричард Столлман)
  • Беседа Сергея Голубева с учителем В.В.Михайловым

  • Википедия или Гуглезнание? Приглашение к обсуждению (Алексей Федорчук)
  • Народная энциклопедия от Google (StraNNik)

  • Обзор Mandriva 2009.0 Beta 1 Thornicrofti
  • Новичок в Линукс: Оптимизируем Mandriva 2008.1

  • Книга Zenwalk. Приобщение к Linux:

    13 августа

    CitCity:

  • Мирный Atom на службе человеку. Обзор платы Intel D945GCLF с интегрированным процессором
  • Обзор процессоров Intel Atom 230 на ядре Diamondville

  • iPhone - год спустя. Скоро и в России?

    CITKIT.ru:

  • Интермедия 3.4. GRUB: установка и настройка (из книги Zenwalk. Приобщение к Linux)

    6 августа

  • СУБД с хранением данных по столбцами и по строкам: насколько они отличаются в действительности? (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Интермедия 2.2. Что неплохо знать для начала (из книги Zenwalk. Приобщение к Linux)

  • И снова про шрифты в Иксах (А.Федорчук)

  • 20 самых быстрых и простых оконных менеджеров для Linux

  • Дело о трех миллиардах (С.Голубев)

    30 июля

  • OLTP в Зазеркалье (Пересказ: С. Кузнецов)

    CitCity:

  • Будущее BI в облаках?
  • Тиражные приложения и заказная разработка. Преимущества для заказчика
  • Дискуссия со сторонниками заказной разработки

    CITKIT.ru:

  • Новые главы книги Zenwalk. Приобщение к Linux:
  • Глава 8. Пакеты: средства установки, системы управления, системы построения
  • Глава 9. Zenwalk: репозитории, пакеты, методы установки

    23 июля

    CITKIT.ru:

  • Все против всех. 64 vs 32, Intel vs AMD, tmpfs vs ext3
  • Две головы от Intel

  • Zenwalk: обзор штатных приложений (глава из книги "Zenwalk. Приобщение к Linux")

  • Нормально, Григорий...

    16 июля

    Обзоры журнала Computer:

  • Перспективы и проблемы программной инженерии в XXI веке
  • Большие хлопоты с большими объемами данных
  • Перспективы наноэлектроники

    CITKIT.ru:

  • Интермедия о лицензиях (А.Федорчук. "Zenwalk. Приобщение к Linux")

  • Есть ли будущее у KDE?

  • Linux в школе: альтернативный вариант в задачах

  • Шифр (приключения агента Никодима)

    10 июля

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия вступительная. Linux или GNU/Linux? Как вас теперь называть?
  • Глава 5. Среда Xfce
  • Глава 6. Xfce: приложения и плагины

  • ZUR (Zenwalk User Repository) FAQ

    2 июля

  • Персистентность данных в объектно-ориентированных приложениях (С. Кузнецов)

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия 1.2. Дорога к Zenwalk'у. Период бури и натиска
  • Интермедия 3.3. Немного о Linux'е и "железе"
  • Глава 4. Настройка: инструментами и руками
  • Интермедия 4.1. Zenpanel и конфиги: поиски корреляции

  • Интервью с Жан-Филиппом Гийоменом, создателем дистрибутива Zenwalk

  • Linux в школе: первые итоги (С. Голубев)

    25 июня

    CITKIT.ru:

  • Zenwalk. Приобщение к Linux (А. Федорчук)

  • Логика и риторика (С.Голубев)

  • Технология Tru64 AdvFS

  • Ханс Райзер предлагает отвести полицейских к телу Нины

    18 июня

  • Проекты по управлению данными в Google (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • ОС и поддержка "железа": мифы и реальность (А. Федорчук)

  • Linux в школе: другие дистрибутивы

  • Пинок (С. Голубев)

    4 июня

  • Ландшафт области управления данными: аналитический обзор (С. Кузнецов)

    CITKIT.ru:

  • Linux в школе: слово заинтересованным лицам

  • SlackBuild: пакеты своими руками

  • Linux от компании Novell. Установка и обзор openSUSE Linux

    Все публикации >>>




  • IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей PR-акции, размещение рекламы — тел. +7 495 4119920, ICQ 232284597 Пресс-релизы — pr@citcity.ru
    Послать комментарий
    Информация для авторов
    Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2007 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...