Смеркалось. Улицы заполнялись свежим вечерним воздухом.
-- Что мы будем делать сегодня, брейн?
-- Как и всегда, в первое сентября, - парсить расписание с tt.kubstu.ru!
Первым делом сливаем жертву на эвм, ну например эту. Самый простой способ преобразовать текст в текст -- с помощью perl и regex. Поэтому сегодня мы будем точить навыки perl-погамистра. Расчехляем perl и приветствуем Larry Wall-a:
$ perl -v
This is perl, v5.10.1 (*) built for i686-cygwin-thread-multi-64int
(with 13 registered patches, see perl -V for more detail)
Copyright 1987-2009, Larry Wall
Perl под windows можно найти в cygwin (это такой tools set из мира linux портированный под windows).
Парсить будем по-колхозному -- регулярками. Скажу вам по секрету, что я жутко ленив и парсер написал только ко второму семестру 4-го курса, примерно тогда у меня завелся телефон на Android. Каждый семестр вручную заполнять календарь как-то не серьезно, а иметь расписание в кармане хочется.
Если вам просто нужно заставить скрипт работать, то достаточно настроить параметры в разделе констант в самом начале скрипта.
Небольшое описание работы скрипта. Начнем с открытия html-файла для чтения, а выхлоп в виде файлов с расписанием лекций и расписанием занятий -- для записи.
Согласно документации Google-календаря записываем заголовок колонок в CSV-формате:
Начинаем построчно читать входной файл и проверять каждую строку на соответствие первой регулярке, которая отвечает за дни недели:
С помощью этой кучи слабо читаемых символов мы заполняем хэш %+ нашими парами занятий с четной и нечетной недели. Конструкции вида (?<Name>Regex) превращаются в именованный массив %+{Name} = Regex, который для наглядности сразу переименовываем в %Lesson.
Теперь нам нужно избавиться от некоторых лишних символов в найденных текстах:
И заполнить календарь до конца учебного семестра, просто пробегаемся по неделям, заполняя сначала первую, а потом вторую:
Некоторые части скрипта опущены, полный исходный код можно найти на bitbucket.org.
Полученные файлы *.csv импортируются в календарь с помощью менюшки "Другие календари".
Удачи!
-- Что мы будем делать сегодня, брейн?
-- Как и всегда, в первое сентября, - парсить расписание с tt.kubstu.ru!
Первым делом сливаем жертву на эвм, ну например эту. Самый простой способ преобразовать текст в текст -- с помощью perl и regex. Поэтому сегодня мы будем точить навыки perl-погамистра. Расчехляем perl и приветствуем Larry Wall-a:
$ perl -v
This is perl, v5.10.1 (*) built for i686-cygwin-thread-multi-64int
(with 13 registered patches, see perl -V for more detail)
Copyright 1987-2009, Larry Wall
Парсить будем по-колхозному -- регулярками. Скажу вам по секрету, что я жутко ленив и парсер написал только ко второму семестру 4-го курса, примерно тогда у меня завелся телефон на Android. Каждый семестр вручную заполнять календарь как-то не серьезно, а иметь расписание в кармане хочется.
![]() |
| Импортированное расписание |
#!/usr/bin/perl # # export-csv.pl # # Created on: 06.02.2012 # Project: ExportScheduleToCSV # License: GPLv3 # # Copyright (c) 2012 brunql #
use constant { INPUT_FILENAME => "5.1.08.K.PO1.htm", FIRST_STUDY_DAY => 3, FIRST_STUDY_MONTH => 9, FIRST_STUDY_YEAR => 12, LAST_STUDY_MONTH => 12 };
Небольшое описание работы скрипта. Начнем с открытия html-файла для чтения, а выхлоп в виде файлов с расписанием лекций и расписанием занятий -- для записи.
open(IMPORT, INPUT_FILENAME) || die("Open import file failed"); open(EXPORT_LECTURES, ">schedule_lectures.csv") || die("Open export file failed"); open(EXPORT_PRACTICE, ">schedule_practice.csv") || die("Open export file failed");
Согласно документации Google-календаря записываем заголовок колонок в CSV-формате:
$Titles = "Subject,Start Date,Start Time,End Date,End Time," . "All Day Event,Description,Location,Private\n"; print EXPORT_LECTURES $Titles; print EXPORT_PRACTICE $Titles;
Начинаем построчно читать входной файл и проверять каждую строку на соответствие первой регулярке, которая отвечает за дни недели:
Промахнулись? Тогда поищем следы лекций и практических занятий в текущей строке:while (<IMPORT>) { if (/ \<th colspan="3" class="dow"\> \<\/th\> \<th colspan="7" class="dow( cb)?"\>(.+)\<\/th\>/x) { $DayOfWeek++; print "\nDay of week:$DayOfWeek\n"; }
elsif (/ \<tr(\ class="bg")?\> \<td\>(?<N>\d)\<\/td\> \<td\ class="terms"\> (?<StartTime>\d\d:\d\d)\<br(\ \/)?\>(?<EndTime>\d\d:\d\d) \<\/td\> \<td\ class="bt_(?<FirstTypeIndex>\d)"\> ( \<span\ class="_p"\>(?<FirstType>.+)\<\/span\> \<span\ class="_s"\> \<\/span\> | ) \<\/td\> \<td\>(?<FirstSubject>.+?) (\<div\ class="note"\>(?<FirstSubjectNote>\(.+\))\<\/div\>)? \<\/td\> \<td(\ class=".")?\>(?<FirstLocation>.+)\<\/td\> \<td\>(?<FirstTeacher>.+)\<\/td\> \<td\ class="bt_(?<SecondTypeIndex>\d)"\> ( \<span\ class="_p"\>(?<SecondType>.+)\<\/span\> \<span\ class="_s"\> \<\/span\> | ) \<\/td\> \<td\>(?<SecondSubject>.+?) (\<div\ class="note"\>(?<SecondSubjectNote>\(.+\))\<\/div\>)? \<\/td\> \<td(\ class=".")?\>(?<SecondLocation>.+)\<\/td\> \<td\>(?<SecondTeacher>.+)\<\/td\>\<\/tr\> /x)
С помощью этой кучи слабо читаемых символов мы заполняем хэш %+ нашими парами занятий с четной и нечетной недели. Конструкции вида (?<Name>Regex) превращаются в именованный массив %+{Name} = Regex, который для наглядности сразу переименовываем в %Lesson.
Теперь нам нужно избавиться от некоторых лишних символов в найденных текстах:
%Lesson = %+;
foreach $key (keys %Lesson) {
$Lesson{$key} =~ s/ //;
$Lesson{$key} =~ s/\,/\ /;
$Lesson{$key} =~ s/\s+/ /g;
}
И заполнить календарь до конца учебного семестра, просто пробегаемся по неделям, заполняя сначала первую, а потом вторую:
while ($DateMonth <= LAST_STUDY_MONTH) { $Date = GetDateDayOfWeek(); if ($FirstSubject && $DateMonth <= LAST_STUDY_MONTH && $WeekCount < $FirstSubjectWeeks) { $line = "$N. $FirstLocation $FirstSubject $FirstType " . "$FirstSubjectNote,$Date,$StartTime,$Date,$EndTime," . "False,$FirstTeacher,$FirstLocation,Private\n"; if ($FirstTypeIndex == 1) { print EXPORT_LECTURES $line; } else { print EXPORT_PRACTICE $line; } } AddWeek(); $Date = GetDateDayOfWeek(); if ($SecondSubject && $DateMonth <= LAST_STUDY_MONTH && $WeekCount < $SecondSubjectWeeks) { $line = "$N. $SecondLocation $SecondSubject $SecondType " . "$SecondSubjectNote,$Date,$StartTime,$Date,$EndTime," . "False,$FirstTeacher,$SecondLocation,Private\n"; if ($SecondTypeIndex == 1) { print EXPORT_LECTURES $line; } else { print EXPORT_PRACTICE $line; } } AddWeek(); }
Некоторые части скрипта опущены, полный исходный код можно найти на bitbucket.org.
Полученные файлы *.csv импортируются в календарь с помощью менюшки "Другие календари".
Удачи!
