Create a gist now

Instantly share code, notes, and snippets.

@xjackk /bttransit.pl
Last active Jan 28, 2016

What would you like to do?
Blacksburg Transit Times
#!/usr/bin/perl
##
## Author: jrk (jaaacckz1@gmail.com)
##
## For my fellow Virginia Tech geeks.
## Get the bus, on time.
##
## Disclaimer : If you get a 400 / POST error, the route you are trying to use does not actually exist.
##
##
## Based on Blacksburg-transit.rb from github.com/mil - a former VT student.
##
use warnings;
use strict;
use URI;
use LWP::Simple;
use Web::Scraper;
use Encode;
use WWW::Mechanize;
use Data::Dumper;
use Switch;
my $site = "http://www.bt4uclassic.org/Mobile.aspx";
my $html = get($site) || die "Couldn't get it";
# adding different routes
# these are taken right from the mobile bt4u site...
my %routes = (
route1 => "TCB - Toms Creek B",
route2 => "TC - Toms Creek",
route3 => "BTC - BT Commuter",
route4 => "CenterCRC - Corporate Research",
route5 => "CRCH - Corporate Research Center/Hospital",
route6 => "HDG - Harding Ave",
route7 => "HWD - Hethwood",
route8 => "HWDA - Hethwood A",
route9 => "HWDB - Hethwood B",
route10 => "HXP - Hokie Express",
route11 => "MSN - Main Street - North",
route12 => "MSS - Main Street - South",
route13 => "PHD - Patrick Henry",
route14 => "PRG - Progress Street",
route15 => "TE - The Explorer",
route16 => "TTT - Two Town Trolley",
route17 => "UCB - University City Blvd",
route18 => "UMS - University Mall"
);
# these are taken right from the mobile bt4u site...
# list of stops
my %stops = (
BurrussHall => "1101 - Burruss Hall",
DavidsonHall => "1102 - Davidson Hall",
WestCampus => "1103 - West Campus/Perry Nbnd",
McBrydeHall => "1106 - McBryde Hall",
HutchesonHall => "1107 - Hutcheson Hall",
WarMemorialHall => "1108 - War Memorial Hall",
SquiresEbnd => "1110 - Squires Ebnd",
AlumniMallEbnd => "1111 - Alumni Mall Ebnd",
AlumniMallWbnd => "1112 - Alumni Mall Wbnd",
SquiresWbnd => "1113 - Squires Wbnd",
RoanokeChurchEbnd => "1500 - Roanoke/Church Ebnd",
RoanokeWhartonEbnd => "1501 - Roanoke/Wharton Ebnd",
RoanokeRutlendEbnd => "1502 - Roanoke/Rutledge Ebnd",
RoanokeWoolwineEbnd => "1503 - Roanoke/Woolwine Ebnd",
HardingOwnesEbnd => "1504 - Harding/Owens Ebnd",
HardingCorkEbnd => "1505 - Harding/Cork Ebnd",
HardingPatrickHenryEbnd => "1506 - Harding/Patrick Henry Ebnd",
HardingAppersonEbnd => "1507 - Harding/Apperson Ebnd",
HardingVistaEbnd => "1508 - Harding/Vista Ebnd",
HardingRoanokeEbnd => "1509 - Harding/Roanoke Ebnd",
AscotHardingEbnd => "1510 - Ascot/Harding Ebnd",
AscotHampton => "1511 - Ascot/Hampton",
AscotHardingWbnd => "1512 - Ascot/Harding Wbnd",
HardingRuckerWbnd => "1513 - Harding/Rucker Wbnd",
HardingSuttonWbnd => "1514 - Harding/Sutton Wbnd",
HardingAppersonWbnd => "1515 - Harding/Apperson Wbnd",
HardingPatrickHenryWbnd => "1516 - Harding/Patrick Henry Wbnd",
HardingCorkWbnd => "1517 - Harding/Cork Wbnd",
RoanokeWoolwineWbnd => "1518 - Roanoke/Woolwine Wbnd",
RoanokeRutledgeWbnd => "1519 - Roanoke/Rutledge Wbnd",
RoanokeWhartonWbnd => "1520 - Roanoke/Wharton Wbnd",
RoanokePennWbnd => "1521 - Roanoke/Penn Wbnd",
MainRoanokeSbnd => "1600 - Main/Roanoke Sbnd",
MainstPostOffice => "1628 - Main St Post Office"
);
my $mech = WWW::Mechanize->new();
$mech->get($site);
print "\n\t BT Transit CLI\n";
print "\t\n Which bus are you trying to catch?\n\n";
print "------------------ \n";
foreach (values %routes) {
print "\t" . " " . $_ . "\n" ;
}
print "\n ------------------ \n\n";
my $id = "Mobile";
my $routebox = "routeListBox";
my $stopbox = "stopListBox";
my $jack = $mech->form_id($id); # get form by id
# get the route we are taking
print "Which route are we taking? (Copy Name Value!)\n";
chomp(my $routeval = <STDIN>);
switch ($routeval) {
case "$routes{route1}" { $routeval = $routes{route1} }
case "$routes{route2}" { $routeval = $routes{route2} }
case "$routes{route3}" { $routeval = $routes{route3} }
case "$routes{route4}" { $routeval = $routes{route4} }
case "$routes{route5}" { $routeval = $routes{route5} }
case "$routes{route6}" { $routeval = $routes{route6} }
case "$routes{route7}" { $routeval = $routes{route7} }
case "$routes{route8}" { $routeval = $routes{route8} }
case "$routes{route9}" { $routeval = $routes{route9} }
case "$routes{route10}" { $routeval = $routes{route10} }
case "$routes{route11}" { $routeval = $routes{route11} }
case "$routes{route12}" { $routeval = $routes{route12} }
case "$routes{route13}" { $routeval = $routes{route13} }
case "$routes{route14}" { $routeval = $routes{route14} }
case "$routes{route15}" { $routeval = $routes{route15} }
case "$routes{route16}" { $routeval = $routes{route16} }
case "$routes{route17}" { $routeval = $routes{route17} }
case "$routes{route18}" { $routeval = $routes{route18} }
}
print "And to which stop are we going? (Copy Route Name)\n\n";
# "This is not the sound of a new man or crispy realization
# It's the sound of the unlocking and the lift away"
foreach (keys %stops) {
print "\t" . " " . $_ . "\n" ;
}
chomp(my $stopval = <STDIN>);
switch ($stopval) {
case "SquiresWbnd" { $stopval = $stops{SquiresWbnd} }
case "HardingVistaEbnd" { $stopval = $stops{HardingVistaEbnd} }
case "RoanokeChurchEbnd" { $stopval = $stops{RoanokeChurchEbnd} }
case "WestCampus" { $stopval = $stops{WestCampus} }
case "RoanokeRutledgeWbnd" { $stopval = $stops{RoanokeRutledgeWbnd} }
case "MainRoanokeSbnd" { $stopval = $stops{MainRoanokeSbnd} }
case "RoanokeWhartonWbnd" { $stopval = $stops{RoanokeWhartonWbnd} }
case "HardingAppersonEbnd" { $stopval = $stops{HardingAppersonEbnd} }
case "MainstPostOffice" { $stopval = $stops{MainstPostOffice} }
case "RoanokeWoolwineWbnd" { $stopval = $stops{RoanokeWoolwineWbnd} }
case "HardingCorkEbnd" { $stopval = $stops{HardingCorkEbnd} }
case "SquiresEbnd" { $stopval = $stops{SquiresEbnd} }
case "AlumniMallWbnd" { $stopval = $stops{AlumniMallWbnd} }
case "HardingPatrickHenryEbnd" { $stopval = $stops{HardingPatrickHenryEbnd} }
case "HardingCorkWbnd" { $stopval = $stops{HardingCorkWbnd} }
case "DavidsonHall" { $stopval = $stops{DavidsonHall} }
case "HardingOwnesEbnd" { $stopval = $stops{HardingOwnesEbnd} }
case "HardingRoanokeEbnd" { $stopval = $stops{HardingRoanokeEbnd} }
case "HardingAppersonWbnd" { $stopval = $stops{HardingAppersonWbnd} }
case "HardingSuttonWbnd" { $stopval = $stops{HardingSuttonWbnd} }
case "AscotHardingEbnd" { $stopval = $stops{AscotHardingEbnd} }
case "RoanokePennWbnd" { $stopval = $stops{RoanokePennWbnd} }
case "HardingRuckerWbnd" { $stopval = $stops{HardingRuckerWbnd} }
case "RoanokeWoolwineEbnd" { $stopval = $stops{RoanokeWoolwineEbnd} }
case "WarMemorialHall" { $stopval = $stops{WarMemorialHall} }
case "AscotHardingWbnd" { $stopval = $stops{AscotHardingWbnd} }
case "AlumniMallEbnd" { $stopval = $stops{AlumniMallEbnd} }
case "RoanokeRutlendEbnd" { $stopval = $stops{RoanokeRutlendEbnd} }
case "HutchesonHall" { $stopval = $stops{HutchesonHall} }
case "RoanokeWhartonEbnd" { $stopval = $stops{RoanokeWhartonEbnd} }
case "HardingPatrickHenryWbnd" { $stopval = $stops{HardingPatrickHenryWbnd} }
case "AscotHampton" { $stopval = $stops{AscotHampton} }
case "BurrussHall" { $stopval = $stops{BurrussHall} }
case "McBrydeHall" { $stopval = $stops{McBrydeHall} }
}
# We have to "click" twice here. The site is setup so it hides the second dropdown until the first is done. Whatever.
# Couldn't find a way to target the javascript hidden field... could come back to this...
# Thank god for WWW::Mechanize
$mech->select($routebox, $routeval);
$mech->click();
$mech->select($stopbox, $stopval);
$mech->click(); # hacky
# return the new html
# the newly rendered page has the "hidden" fields
# parsed response
my $newhtml = $mech->response();
## Whoever wrote this page really isn't too great.
## Here we are going to do the scraping, once the form has been worked on, we have access to stop time.
## We can pass in the parsed html response instead of the URL.
my $stoptimes = scraper {
process "li", "stops[]" => scraper {
process 'span', time => 'TEXT';
};
};
# "I toured the light
# So many foreign roads
# For Emma, forever ago."
my $stopresponse = $stoptimes->scrape(($newhtml));
print "\n";
for my $times (@{$stopresponse->{stops}}) {
print $times->{time};
print "\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment