- Регистрация
- 25.01.17
- Сообщения
- 763
- Реакции
- 225
- Репутация
- 292
Еще один PERL-парсер
Сегодня я расскажу о скрипте, который помогал мне обрабатывать данные при подготовке ежемесячных отчетов об изменении рейтинга на ав-скул. Эта статья призвана компенсировать отсутствие отчета за август (которого небыло по причине уже подведенных итогов), так как по-ходу вы и так узнаете, какие изменения произошли за этот месяц.
Начинается все с того, что у меня есть две сохраненные странички: 20100801.html и 20100901.html. Это просто сохраненная, соответственно, первого августа и первого сентября страница
"Работу" (если так можно назвать вырезание частей скриншотов и помещение их в один файл) с графикой я произвожу обычно в GIMP или Paint, в зависимости от используемой операционной системы. Чаще GIMP.
Когда я подсчитывал изменения рейтинга в первый раз, то просто скопировал данные со страниц в таблицу и хотел используя простую формулу подсчитать разность баллов. Вы наверное уже догадались с какой трудностью я столкнулся. Это выглядело примерно так:
В крайней правой колонке что-то вроде "=E13-B13", растянутое на всю таблицу. То есть разность между рейтингом в начале августа и в начале сентября. Но уже с четвертого места произошли изменения в занимаемом месте. И таких изменений иногда бывает очень много. Фактически до какого-то момента неизменной оставались лишь шесть первых мест, а остальные постоянно перетасовывались. Кроме того, уже в первом же обзоре выяснилось, что участник легко может сменить ник. Соответственно, привязка к нику тоже может подвести.
Соответственно, потаскав данные по ячейкам экселечки, было принято решение как-то автоматизировать процедуру подсчета изменений. В качестве инструмента для этого я выбрал, как обычно, PERL. И конечно же MySQL для хранения данных.
Какие данные нам потребуются? Во-первых, дата. Сначала я хотел брать число прямо со страницы:
Однако, иногда там написано просто:
Поэтому дату я стал брать из названия файла.
Вместо ника нужно брать id-пользователя. Его можно узнать из ссылки на профиль -
Ну а текущий рейтинг - это просто текущий рейтинг.
Таким образом таблица в 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, второй - рейтинг. При этом каждому элементу одного массива строго соответствует такой же элемент второго массива.
На данном этапе можно помещать в базу все собранные данные:
Перебираем массивы @Ratio и @UIDs. Помещаем в базу дату, полученную из имени файла в самом начале, id пользователя из массива @UIDs, вместо ника пока вставляем в базу "-1", и текущий рейтинг из массива @Ratio.
После всего этого переходим к следующему файлу в каталоге с сохраненными страницами и повторяем до тех пор, пока файлы не закончатся.
Получив в свое распоряжение такую базу можно сформировать таблицу, в которой проводить расчеты будет проще. Что-то вроде такого:
Верхняя строчка - юиды, левый столбец - даты. Пустые ячейки образовались там, где участников небыло при одном из подсчетов. То есть либо выбыл из таблицы, либо добавился. В апреле я не ленился сохранять рейтинг каждый день и можно было даже строить графики хоть для каждого участника с точностью до дня.
Для пущего удобства можно внести в базу и ники. Это просто сделать имея номера. Автоматически формируем список вида:
Впрочем, основных завсегдатаев я уже и по айдишнику узнаю.
Вот такая автоматизация и позволяет мне делать обзоры рейтинга довольно оперативно и вроде бы даже без ошибок.
Но есть еще одна деталь, которую не подскажет ни один скрипт - отношение ко всем участникам, как живым людям, а не просто как к цифрам на страничке. Так что вы уж постарайтесь быть еще активнее и заметнее, чтобы было чем подбодрить и поддержать каждого!
Сегодня я расскажу о скрипте, который помогал мне обрабатывать данные при подготовке ежемесячных отчетов об изменении рейтинга на ав-скул. Эта статья призвана компенсировать отсутствие отчета за август (которого небыло по причине уже подведенных итогов), так как по-ходу вы и так узнаете, какие изменения произошли за этот месяц.
Начинается все с того, что у меня есть две сохраненные странички: 20100801.html и 20100901.html. Это просто сохраненная, соответственно, первого августа и первого сентября страница
You must be registered for see links
, то есть данные на начало месяца и на конец."Работу" (если так можно назвать вырезание частей скриншотов и помещение их в один файл) с графикой я произвожу обычно в GIMP или Paint, в зависимости от используемой операционной системы. Чаще GIMP.
Когда я подсчитывал изменения рейтинга в первый раз, то просто скопировал данные со страниц в таблицу и хотел используя простую формулу подсчитать разность баллов. Вы наверное уже догадались с какой трудностью я столкнулся. Это выглядело примерно так:
В крайней правой колонке что-то вроде "=E13-B13", растянутое на всю таблицу. То есть разность между рейтингом в начале августа и в начале сентября. Но уже с четвертого места произошли изменения в занимаемом месте. И таких изменений иногда бывает очень много. Фактически до какого-то момента неизменной оставались лишь шесть первых мест, а остальные постоянно перетасовывались. Кроме того, уже в первом же обзоре выяснилось, что участник легко может сменить ник. Соответственно, привязка к нику тоже может подвести.
Соответственно, потаскав данные по ячейкам экселечки, было принято решение как-то автоматизировать процедуру подсчета изменений. В качестве инструмента для этого я выбрал, как обычно, PERL. И конечно же MySQL для хранения данных.
Какие данные нам потребуются? Во-первых, дата. Сначала я хотел брать число прямо со страницы:
Однако, иногда там написано просто:
Поэтому дату я стал брать из названия файла.
Вместо ника нужно брать id-пользователя. Его можно узнать из ссылки на профиль -
You must be registered for see links
, соответственно у 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 и рейтинг? Сначала ее нужно разделить по ключевой фразе:
You must be registered for see links
. После тире идет как раз id. Таким образом у нас получится массив, первым элементом которого будет ненужный кусок, от которого мы избавимся, а остальные куски будут начинаться с цифр id. Поэтому от первого элементы мы избавляемся: shift(@stage1);, а остальные строки будут выглядеть как-то так:Как видно, достать id нетрудно - достаточно взять часть строки до первых кавычек. Это делаем следующим циклом:
Делим строку по кавычкам и сохраняем первый элемент.
Для получения количества баллов эту же строку нужно поделить так:
Чтобы добраться до цифр, подчеркнутых красным, нужно резать по ключевой строке, подчеркнутой синим. А потом отбросить все, что после цифр. За это отвечает такой код:
В итоге, мы получаем два массива, состоящих из одинакового количества элементов. Один содержит id, второй - рейтинг. При этом каждому элементу одного массива строго соответствует такой же элемент второго массива.
На данном этапе можно помещать в базу все собранные данные:
Перебираем массивы @Ratio и @UIDs. Помещаем в базу дату, полученную из имени файла в самом начале, id пользователя из массива @UIDs, вместо ника пока вставляем в базу "-1", и текущий рейтинг из массива @Ratio.
После всего этого переходим к следующему файлу в каталоге с сохраненными страницами и повторяем до тех пор, пока файлы не закончатся.
Получив в свое распоряжение такую базу можно сформировать таблицу, в которой проводить расчеты будет проще. Что-то вроде такого:
Верхняя строчка - юиды, левый столбец - даты. Пустые ячейки образовались там, где участников небыло при одном из подсчетов. То есть либо выбыл из таблицы, либо добавился. В апреле я не ленился сохранять рейтинг каждый день и можно было даже строить графики хоть для каждого участника с точностью до дня.
Для пущего удобства можно внести в базу и ники. Это просто сделать имея номера. Автоматически формируем список вида:
You must be registered for see links
+ номер, а затем парсим скачанные страницы с профилями. Потом просто обновляем таблицы запросом "UPDATE 'ratio' SET name='$name' WHERE uid='$id';" и таблица будет уже такой:Впрочем, основных завсегдатаев я уже и по айдишнику узнаю.
Вот такая автоматизация и позволяет мне делать обзоры рейтинга довольно оперативно и вроде бы даже без ошибок.
Но есть еще одна деталь, которую не подскажет ни один скрипт - отношение ко всем участникам, как живым людям, а не просто как к цифрам на страничке. Так что вы уж постарайтесь быть еще активнее и заметнее, чтобы было чем подбодрить и поддержать каждого!