Еще один PERL-парсер Сегодня я расскажу о скрипте, который помогал мне обрабатывать данные при подготовке ежемесячных отчетов об изменении рейтинга на ав-скул. Эта статья призвана компенсировать отсутствие отчета за август (которого небыло по причине уже подведенных итогов), так как по-ходу вы и так узнаете, какие изменения произошли за этот месяц. Начинается все с того, что у меня есть две сохраненные странички: 20100801.html и 20100901.html. Это просто сохраненная, соответственно, первого августа и первого сентября страница , то есть данные на начало месяца и на конец. "Работу" (если так можно назвать вырезание частей скриншотов и помещение их в один файл) с графикой я произвожу обычно в GIMP или Paint, в зависимости от используемой операционной системы. Чаще GIMP. Когда я подсчитывал изменения рейтинга в первый раз, то просто скопировал данные со страниц в таблицу и хотел используя простую формулу подсчитать разность баллов. Вы наверное уже догадались с какой трудностью я столкнулся. Это выглядело примерно так: В крайней правой колонке что-то вроде "=E13-B13", растянутое на всю таблицу. То есть разность между рейтингом в начале августа и в начале сентября. Но уже с четвертого места произошли изменения в занимаемом месте. И таких изменений иногда бывает очень много. Фактически до какого-то момента неизменной оставались лишь шесть первых мест, а остальные постоянно перетасовывались. Кроме того, уже в первом же обзоре выяснилось, что участник легко может сменить ник. Соответственно, привязка к нику тоже может подвести. Соответственно, потаскав данные по ячейкам экселечки, было принято решение как-то автоматизировать процедуру подсчета изменений. В качестве инструмента для этого я выбрал, как обычно, PERL. И конечно же MySQL для хранения данных. Какие данные нам потребуются? Во-первых, дата. Сначала я хотел брать число прямо со страницы: Однако, иногда там написано просто: Поэтому дату я стал брать из названия файла. Вместо ника нужно брать id-пользователя. Его можно узнать из ссылки на профиль - , соответственно у alextim id=844. Ну а текущий рейтинг - это просто текущий рейтинг. Таким образом таблица в MySQ имеет всего 4 поля - дата, id, ник, рейтинг. Вот и переходим к скрипту, который все это обрабатывает. Начинается все с подключения к базе: Запрос DROP TABLE IF EXISTS 'ratio'; удалит уже существующую таблицу. Это было сделано в начале в целях отладки - приходилось постоянно в ручную удалять введенные данные, чтобы они не путались с новыми и было проще искать ошибки, если они возникнут. Потом запрос так и остался. Затем мы сканируем каталог, с сохраненными файлами и получаем из имен даты: В переменную $filename по очереди помещаются имена файлов, находящихся в каталоге HOMEDIR. Имя каталога задается в переменной $dir. При этом, если имя файла равно точке или двум точкам, то обработка файла не производится. Что за файлы имеют такие странные имена? Об этом можно узнать в википедии. Коротко - ".." обозначает каталог, находящийся на один выше текущего, а "." - текущий каталог. В общем, чтобы не отвлекать вас ненужными подробностями - каждый каталог содержит файлы с такими именами, но нас они не интересуют. Так как файлы имеют формат названия <date>.html, то из него нужно удалить ".html". Для этого делим имя файла по точке: split( /\./, $filename ); и сохраняем то, что до этой самой точки: $filename = $temp[0]; И сохраняем полученное в переменную $date = $filename; После этого, выбранный и открытый файл помещается в массив, в котором он разделен на отдельные строки: @file_to_parse = <INFILE>; Теперь из всех строк нам нужно выбрать ту, в которой содержатся данные о рейтинге. Такая строка в файле всего одна, но она здоровущая. Ее можно найти, открыв код страницы с рейтингом и поискав по 'td class=" topname"' Но перед обработкой необходимо конвертировать строку из по непонятным причинам используемой кодировки windows-1251 в куда более современный и общепринятый utf-8. Все это и происходит вот тут: Строка выбрана. Как же из нее выбрать id и рейтинг? Сначала ее нужно разделить по ключевой фразе: . После тире идет как раз id. Таким образом у нас получится массив, первым элементом которого будет ненужный кусок, от которого мы избавимся, а остальные куски будут начинаться с цифр id. Поэтому от первого элементы мы избавляемся: shift(@stage1);, а остальные строки будут выглядеть как-то так: Как видно, достать id нетрудно - достаточно взять часть строки до первых кавычек. Это делаем следующим циклом: Делим строку по кавычкам и сохраняем первый элемент. Для получения количества баллов эту же строку нужно поделить так: Чтобы добраться до цифр, подчеркнутых красным, нужно резать по ключевой строке, подчеркнутой синим. А потом отбросить все, что после цифр. За это отвечает такой код: В итоге, мы получаем два массива, состоящих из одинакового количества элементов. Один содержит id, второй - рейтинг. При этом каждому элементу одного массива строго соответствует такой же элемент второго массива. На данном этапе можно помещать в базу все собранные данные: Перебираем массивы @Ratio и @UIDs. Помещаем в базу дату, полученную из имени файла в самом начале, id пользователя из массива @UIDs, вместо ника пока вставляем в базу "-1", и текущий рейтинг из массива @Ratio. После всего этого переходим к следующему файлу в каталоге с сохраненными страницами и повторяем до тех пор, пока файлы не закончатся. Получив в свое распоряжение такую базу можно сформировать таблицу, в которой проводить расчеты будет проще. Что-то вроде такого: Верхняя строчка - юиды, левый столбец - даты. Пустые ячейки образовались там, где участников небыло при одном из подсчетов. То есть либо выбыл из таблицы, либо добавился. В апреле я не ленился сохранять рейтинг каждый день и можно было даже строить графики хоть для каждого участника с точностью до дня. Для пущего удобства можно внести в базу и ники. Это просто сделать имея номера. Автоматически формируем список вида: + номер, а затем парсим скачанные страницы с профилями. Потом просто обновляем таблицы запросом "UPDATE 'ratio' SET name='$name' WHERE uid='$id';" и таблица будет уже такой: Впрочем, основных завсегдатаев я уже и по айдишнику узнаю. Вот такая автоматизация и позволяет мне делать обзоры рейтинга довольно оперативно и вроде бы даже без ошибок. Но есть еще одна деталь, которую не подскажет ни один скрипт - отношение ко всем участникам, как живым людям, а не просто как к цифрам на страничке. Так что вы уж постарайтесь быть еще активнее и заметнее, чтобы было чем подбодрить и поддержать каждого! Предлагаю услуги по: 1. Сделаю зеркало любого сайта в сети ТОR 2. Блокировка ЛЮБОГО QIWI Номера (Быстро) Мануалы и софт выложены в ознакомительных целях вся ответственность за использования ложится на вас. Софт советую использовать на виртуалке.