def submitToTimetable(self, term, crn): if (self.currentPage != self.TIMETABLE): cg_io.printError(4) print "Terminating...\n" exit(-1) self.browser.select_form('ttform') form = list(self.browser.forms())[1] termYear = form.find_control("TERMYEAR") termYear.value = [str(termYear.possible_items()[term])] form.find_control('crn').value = crn # Submit self.browser.submit() # Check validity html = self.browser.response().read() soup = BeautifulSoup(str(html), 'html5lib') # Bad crn? if (soup.find('li', text = re.compile('NO SECTIONS FOUND FOR THIS INQUIRY.')) != None): return False # Ok self.currentPage = self.TIMETABLE return True
def locateAndParseTerms(self): if (self.currentPage != self.TIMETABLE): cg_io.printError(4) print "Terminating...\n" exit(-1) rawItems = list(self.browser.forms())[1].find_control("TERMYEAR").possible_items() parsedItems = [] for item in rawItems: item = int(item) # Math month = item % 10 year = (item - (item % 100)) / 100 if (month == 1): month = "Spring" elif (month == 6): month = "Summer I" elif (month == 7): month = "Summer II" elif (month == 9): month = "Fall" parsedItems.append(month + " " + str(year)) return [parsedItems, rawItems]
def navigateToTimetable(self): if (self.currentPage != self.REGISTRATION_AND_SCHEDULE): cg_io.printError(3) print "Terminating...\n" exit(-1) this_link = list(self.browser.links(text_regex = 'Timetable of Classes'))[0] self.browser.follow_link(this_link) self.currentPage = self.TIMETABLE
def submitToLoginPage(self, username, password): # On login page? if (self.currentPage != self.LOGIN_PAGE): cg_io.printError(1) print "Terminating...\n" exit(-1) result = _attemptLogin(username, password, self.browser) if (result == True): self.currentPage = self.LANDING_PAGE return result
def navigateToRegAndSch(self): if (self.currentPage != self.LANDING_PAGE): cg_io.printError(5) print "Terminating...\n" exit(-1) this_link = list(self.browser.links(text_regex = 'Hokie Spa'))[0] self.browser.follow_link(this_link) this_link = list(self.browser.links(text_regex = 'Registration and Schedule'))[0] self.browser.follow_link(this_link) self.currentPage = self.REGISTRATION_AND_SCHEDULE
def navigateToDropAdd(self, term): if (self.currentPage != self.REGISTRATION_AND_SCHEDULE): cg_io.printError(3) print "Terminating..." exit(-1) # Try to find the add course button theseLinks = list(self.browser.links(url_regex = '/ssb/prod/bwskfreg\.P_AddDropCrse\?term_in=' + str(term))) self.browser.follow_link(these_links[0]) self.currentPage = self.DROP_ADD
def checkDropAddExists(self): if (self.currentPage != self.REGISTRATION_AND_SCHEDULE): cg_io.printError(3) print "Terminating..." exit(-1) # Try to find the add course button theseLinks = list(self.browser.links(text_regex = 'Drop/Add')) # If drop/add isn't open if (len(theseLinks) == 0): return False return True
def submitToDropAdd(self, crn): if (self.currentPage != self.DROP_ADD): cg_io.printError(7) print "Terminating..." exit(-1) # Select the form and control addForm = list(self.browser.forms())[1] self.browser.form = addForm termControl = addForm.find_control(id='crn_id1') termControl.value = str(crn) # Try and submit self.browser.submit()
def locateAndParseTimetableResults(self): if (self.currentPage != self.TIMETABLE): cg_io.printError(6) print "Terminating..." html = self.browser.response().read() soup = BeautifulSoup(str(html), 'html5lib') data_left = soup.findAll('td', attrs = {'class' : 'deleft'}) data_center = soup.findAll('td', attrs = {'class' : 'dedefault'}) data_right = soup.findAll('td', attrs = {'class' : 'deright'}) class_num = _stripTags(str(data_left[0])).strip() class_name = _stripTags(str(data_left[1])) prof = _stripTags(str(data_left[2])) location = _stripTags(str(data_left[3])) credits = _stripTags(str(data_center[2])).strip() seats = _stripTags(str(data_center[3])).strip() days = _stripTags(str(data_center[4])).strip() # Declare isOnline = False startTime = -1 endTime = -1 # Online? if (len(data_center) == 7): isOnline = True else: startTime =_stripTags(str(data_right[0])) endTime = _stripTags(str(data_right[1])) regexSeat = re.compile('Full (0|-\d*) / [\d]*') classFull = re.match(regexSeat, seats) return {"classNumber": class_num, "className": class_name, "professor": prof, "location": location, "credits": credits, "seats": seats, "days": days, "isOnline": isOnline, "startTime": startTime, "endTime": endTime, "full": classFull}
def runNormally(unsafe): cg_io.printWelcome() print "Preparing. Wait...\n" # Get a scraper going mainScraper = navigator.Scraper() mainScraper.navigateToLoginPage() success = False # While you cannot login while (success != True): credentialsList = cg_io.requestCredentials() # Check for <q> if (credentialsList[0] == "q"): print "Exiting...\n" return cg_io.waitMessage() success = mainScraper.submitToLoginPage(credentialsList[0], credentialsList[1]) if (success != True): cg_io.printLoginFailure() pool = 0 setupThread = ThreadWithReturnValue(target=_setupResources, args=[mainScraper, unsafe]) setupThread.start() print "Login successful. Welcome, " + credentialsList[0] + "!" print "Ready\n" # Run-time loop command = -1 while (True): command = cg_io.takeCommand() killRegex = re.compile("kill \d+") evalRegex = re.compile("eval \d+") # Quit operation if (command == "quit"): # Try to quit, shutting down the pool if (pool == 0): break elif (pool.hasJobs()): result = cg_io.requestQuit() if (result == True): break print "Backing out...\n" continue # Help operation elif (command == "help"): cg_io.printHelp() continue # Debug operation elif (command == "debug"): print "<return> key at any time to leave debugging context." pool.broadcastDebug(True) crn = raw_input("") pool.broadcastDebug(False) # Add operation elif (command == "add"): cg_io.waitMessage() # Pool ready? if (pool == 0): pool = grinder.GruntPool(30) # Wait to join result = setupThread.join() if (result == -1): cg_io.printNoDropAdd() break # This loop is here because we have to make sure that the CRN is valid # You only know if the CRN is valid after submitting, so the loop goes here backingOut = False while(True): term = cg_io.requestTermSelection(mainScraper.locateAndParseTerms()[0]) # Quitting if (term == -1): print "Backing out...\n" backingOut = True break crn = cg_io.requestCrn() # Quitting if (crn == -1): print "Backing out...\n" backingOut = True break cg_io.waitMessage() if (mainScraper.submitToTimetable(term, crn) == True): break cg_io.printError(6) if (backingOut == True): continue # Report results dictionary = mainScraper.locateAndParseTimetableResults() cg_io.printTimetableResultDictionary(dictionary) answer = cg_io.requestAddAction(dictionary) # Add a job to the grinder if (answer == True): copyScraper = navigator.clone(mainScraper) pool.releaseGrunt(dictionary, term, crn, copyScraper) print "Job added\n" continue else: print "Backing out...\n" continue # Job reporting elif (command == "jobs"): allJobs = pool.getRunningList() somethingToDisplay = False if (len(allJobs) > 0): somethingToDisplay = True print "Busy:" for i in range(0, len(allJobs)): if (i == len(allJobs) - 1 and len(pool.getDoneList()) == 0): print "[" + str(i) + "]: " + allJobs[i] + "\n" else: print "[" + str(i) + "]: " + allJobs[i] allJobs = pool.getDoneList() if (len(allJobs) > 0): somethingToDisplay = True print "Done:" for i in range(0, len(allJobs)): if (i == len(allJobs) - 1): print allJobs[i] + "\n" else: print allJobs[i] pool.doneJobs = [] if (somethingToDisplay == False): print "No jobs to display\n" continue # Kill operation elif (killRegex.search(command) != None): jobNum = map(int, re.findall("\d+", command))[0] if (len(pool.getRunningList()) <= 0): print "No jobs to kill\n" continue if (jobNum < 0 or jobNum >= len(pool.getRunningList())): print "Only type a valid job number.\n" continue print "Killing job number " + str(jobNum) + "\n" pool.stopGrunt(jobNum) continue # Eval operation elif (evalRegex.search(command) != None): evalRate = map(int, re.findall("\d+", command))[0] if (evalRate < 5): print "Cannot use an evaluation rate less than 5 seconds.\n" else: pool.changeRate(evalRate) print "Jobs will check for open seats every " + str(evalRate) + " seconds\n" # Cannot understand command else: cg_io.printError(2) continue cg_io.printQuitting() if (pool != 0): pool.shutdown() return