As with any other college, trying to get the classes you want at Virginia Tech can be difficult when they're full. Most people are left to waste time refreshing the class timetable. Well I decided to make the computer work for me and tell me the minute a class opens up.
I really wanted a class at 11am on Tuesdays and Thursdays, and I saw "Music Theory and Fundamentals" was at that time. I play piano and want to learn more about making music, so I thought it'd be an interesting class to take, but it was full and chances looked slim at catching it open. So I wrote a Perl script to check the timetable every minute (because that's the fastest a cron job will let me) and then send me a text message when there is an opening in the class. Here is the final masterpiece:
#!/usr/bin/perl -w
use strict;
use WWW::Mechanize;
use HTML::TokeParser;
my $crn = "14484";
my $agent = WWW::Mechanize->new();
$agent->get("https://banweb.banner.vt.edu/ssb/prod/HZSKVTSC.P_ProcRequest");
$agent->form_number(1);
$agent->field("crn", $crn);
$agent->click();
my $stream = HTML::TokeParser->new(\$agent->{content});
$stream->get_tag("table");
$stream->get_tag("table");
$stream->get_tag("table");
$stream->get_tag("table");
$stream->get_tag("table");
$stream->get_tag("tr");
$stream->get_tag("tr");
$stream->get_tag("td");
$stream->get_tag("td");
$stream->get_tag("td");
my $classname = $stream->get_trimmed_text("td");
$stream->get_tag("td");
$stream->get_tag("td");
$stream->get_tag("td");
$stream->get_tag("p");
my $status = $stream->get_trimmed_text("/b");
my $now = localtime time;
open(httpd_log, ">>/Users/kevin/cronlog.txt");
print httpd_log "[$now] [$crn] $classname: $status\n";
close httpd_log;
if ($tag ne "Full") {
open (MAIL, "|/usr/sbin/sendmail -t ");
print MAIL "From: k\@vt.edu\n";
print MAIL "To: phonenumber\@txt.att.net\n";
print MAIL "Content-Type: text/plain\n";
print MAIL "Subject: $classname ($crn)\n\n";
print MAIL "$status";
close (MAIL);
} else {
# else...
}Actually, it's not that great of a script. There are some bugs, but the basic features are in there that I want to show you. (WARNING, GEEK CONTENT) It requires the latest versions of WWW::Mechanize and WWW::TokeParser. Mechanize will let you submit forms, which I needed because the timetable doesn't pass variables through the URL. TokeParser is then used to grab text from the site. All those $stream->get_tag() functions tell TokeParser where to go on the page, and assign variables to certain text on the way down.
Why a cron job? Why not a loop with a sleep function? The script would crash after a few hours, mainly because the timetable isn't very reliable. I didn't feel like building in error handling, so I set up a cron job so I know the script would run every minute no matter what happens. I had it output the results into a log so I would know the script was still working, and I would embed it on my desktop with GeekTool. It would look like this:
[Thu Jan 8 09:18:02 2009] [15312] Introduction to Acting: Full [Thu Jan 8 09:18:02 2009] [14484] Theory/Fundamentals: 1 / 60 [Thu Jan 8 09:19:02 2009] [15312] Introduction to Acting: Full [Thu Jan 8 09:19:02 2009] [14484] Theory/Fundamentals: 1 / 60
I was also watching Intro to Acting as a backup, which also had the same timeslot. This is the point in the log in which there was an opening in the class and it sent me a text message. It was awesome to know that I actually pulled it off and that it all worked. I could have even had the script log into the class drop/add system and add the class for me, but I thought I'd just do it myself once I got the text message.
So there it is kids, this is my last semester so I won't be needing it anymore. I hope you've learned something, and leave a comment if you have any questions.