#!/usr/bin/perl use warnings; use strict; use WWW::Mechanize; use HTML::TokeParser; use CGI; my $id = YOUR_ID_HERE; #use quotes! my $pin = YOUR_PIN_HERE; #use quotes! my $semester = shift; my $courses = shift; my $cgi = CGI->new(); my $form = $cgi->Vars; my $agent = WWW::Mechanize->new(cookie_jar=>{}); $agent->get('https://poseidon.cc.mcgill.ca/pls/mcgp/twbkwbis.P_WWWLogin'); $agent->form(2); $agent->field('sid', $id); $agent->field('PIN', $pin); $agent->click(); $agent->get('https://poseidon.cc.mcgill.ca/pls/mcgp/bzsktran.P_Display_Form?user_type=S&tran_type=V'); if (!($agent->content =~ m/TERM GPA/)) { die("Error accessing transcript. Perhaps system is busy or bad login information?\n"); } my @semmatch = ($agent->content =~ m@(?:(.*?.*?.*?)(?:TERM GPA|START OF).*?){$semester}@si); my @grades; my @nogrades; my $count; my @matches; for ($count=1; $count <= $courses; $count++) { @matches = ( $semmatch[0] =~ m@.*?(?:\s*]+>(?:]+>)?([^<]+)(?:)?\s*]+>]+>([^<]+)(?: ]+>[^<]+)?\s*]+>]+>([^<]+)\s*]+>]+>([^<]+)\s*]+>]+>([^<]+)\s*]+>[^<]+\s*]+>(?:]+>)?([^<]+)(?:)?.*?.*?){$count}@si ); if ($matches[5] ne " ") { $grades[$#grades+1] = " " . $matches[5] . " in " . $matches[1] . " (" . $matches[3] . ")"; } else { $nogrades[$#nogrades+1] = $matches[1]; } } $agent->get('https://poseidon.cc.mcgill.ca/pls/mcgp/twbkwbis.P_Logout'); if ($#grades >= 0) { print "Available grades:\n" . join("\n", @grades) . "\n"; } if ($#nogrades >= 0) { print "Grades not available for " . join(", ", @nogrades) . ".\n"; }