Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ###################
- # Script Name: Scrape Bluehost Queues
- # Author: Brandon West
- # Date created: 11/11/2014
- # Date last modified: 11/23/2014
- # Autokey Version: 0.71.2
- # Description: Quickly query wallboards for queue values
- ## to be entered into the L3 Trends Google Doc
- # Setup: $ sudo pip install mechanize beautifulsoup4 requests
- ###################
- import re
- import requests
- import mechanize
- import cookielib
- from bs4 import BeautifulSoup
- ###### SUPPORTING QUEUE CLASS ######
- #Queue:
- # queue_id
- # queue_name
- # queue_type
- # count_customers_in_queue
- # top_wait_time
- # avg_wait_time
- # count_techs_logged_in
- # count_techs_with_customers
- # count_techs_unavailable
- # count_techs_available
- # Create a class for Queue objects to store attributes about each queue.
- class Queue:
- 'Common class for all queue types'
- def __init__(self, queue_type, queue_id, queue_name, count_customers_in_queue, top_wait_time, avg_wait_time, count_techs_logged_in, count_techs_with_customers, count_techs_unavailable, count_techs_available):
- self.type = queue_type
- self.id = queue_id
- self.name = queue_name
- self.type = queue_type
- self.count_customers_in_queue = count_customers_in_queue
- self.top_wait_time = top_wait_time
- self.avg_wait_time = avg_wait_time
- self.count_techs_logged_in = count_techs_logged_in
- self.count_techs_with_customers = count_techs_with_customers
- self.count_techs_unavailable = count_techs_unavailable
- self.count_techs_available = count_techs_available
- def __hash__(self):
- return hash((self.id, self.name))
- def displayAll(self):
- print "Queue ID: ", self.id
- print "Queue Name: ", self.name
- print " Queue Type: ", self.type
- print " Customers Waiting: ", self.count_customers_in_queue
- print " Top Wait Time: ", self.top_wait_time
- if self.type == "call":
- print " Avg. Wait Time: ", self.avg_wait_time
- print " Techs Logged In: ", self.count_techs_logged_in
- print " Techs with Customers: ", self.count_techs_with_customers
- print " Techs Unavailable: ", self.count_techs_unavailable
- print " Techs Available: ", self.count_techs_available
- ###### START PRIMARY SCRIPT ######
- BH_LOGIN_URL = "https://i.bluehost.com/cgi/admin/provider"
- CHATS_URL = "https://i.bluehost.com/cgi-bin/util/live_chat/live_chat?skip_wrapper=1"
- CALLS_URL = "https://wallboard.bluehost.com/wallboard/wallboard_call.html"
- UNAME = system.exec_command("bash -c 'whoami'", True)
- ### [0-1] are identical because the class ID for Support Calls and Chats are the same.
- ### The order of SELECTED_QUEUES defines final output order
- SELECTED_QUEUES = [("Support Calls", "queue_support"), ("Support Chats", "queue_support"), ("Level 3 Calls", "queue_level_3"), ("Dedicated Chats", "queue_dedicated")]
- QUEUE_DATA = []
- ###### Set up mechanize browser ######
- ##Browser
- agent = mechanize.Browser()
- ##Cookie Jar
- cj = cookielib.LWPCookieJar()
- ##Browser Options
- agent.set_cookiejar(cj)
- agent.set_handle_equiv(True)
- agent.set_handle_redirect(True)
- agent.set_handle_referer(True)
- agent.set_handle_robots(False)
- agent.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)
- ## Adding request headers
- agent.addheaders = [('User-agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0'),
- ('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'),
- ('Accept-Language', 'en-gb,en;q=0.5'),
- ('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7')]
- ## If cookie not found, log in and store session for use
- def bh_login_check():
- agent.open(BH_LOGIN_URL)
- try:
- cj._cookies['i.bluehost.com']['/']['admin_user']
- except KeyError:
- # print "there was an error"
- agent.select_form(name="admin_login_form")
- for control in agent.form.controls:
- if control.name == 'admin_user':
- agent[control.name] = UNAME
- if control.name == 'admin_pass':
- retCode, webpass = dialog.password_dialog(title="Login - i.bluehost.com", message="Enter web password for user: \n %s" % UNAME)
- agent[control.name] = webpass
- ## submitting the loginform
- response = agent.submit()
- try:
- agent.select_form(name="admin_login_form")
- except mechanize._mechanize.FormNotFoundError:
- return True
- else:
- # TODO: need to get the info dialog to display when auth fails
- #print "Sorry, Cannot Log in to Bluehost. Wrong password?"
- #dialog.info_dialog(title="Authorization Failed", message="Sorry, Cannot Log in to Bluehost. Wrong password?")
- return False
- # print response.read()
- # Check each wallboard queue, collect and store relevant values for the report
- def scrape_queues():
- ## Get calls wallboard report
- queue_urls = [CALLS_URL, CHATS_URL]
- for queue_url in queue_urls:
- resource_calls = agent.open(queue_url)
- soup_calls = BeautifulSoup(resource_calls.read())
- support_queues= soup_calls.find_all('div', {'class' : 'queue'})
- ## Create queue objects with current values for the appropriate call queues.
- for queue in support_queues:
- queue_type = ""
- queue_name = ""
- queue_awt = 0
- queue_customers_waiting = 0
- queue_calls_waiting = 0
- queue_top_wait_time = 0
- queue_techs_available = 0
- queue_techs_logged_in = 0
- queue_techs_with_customers = 0
- count_techs_unavailable = 0
- queue_techs_available = 0
- call_queue = ""
- queue_id = queue.get('id')
- if queue_id in dict(SELECTED_QUEUES).values():
- queue_name = queue.find('td', {'class' : 'top_header'}).contents[0]
- queue_customers_waiting = queue.find('td', {'class' : 'total_count'}).contents[0]
- queue_customers_waiting = "".join(line.strip() for line in queue_customers_waiting.split("\n"))
- queue_top_wait_time = queue.find('td', {'class' : 'top_waiting'}).contents[0]
- if queue_url == CALLS_URL:
- ## custom Calls-specific attribute
- queue_type = "call"
- queue_awt = queue.find('td', {'id' : 'awtTd'}).contents[0]
- queue_awt = queue_awt.strip(" ")
- queue_techs_info = queue.find('td', {'id' : lambda L: L and L.startswith('avail_techs')}).contents[0]
- queue_techs_info = queue_techs_info.strip(" \n")
- queue_techs_info = re.split('/', queue_techs_info)
- queue_techs_with_customers = queue_techs_info[0].strip(" \n")
- queue_techs_logged_in = queue_techs_info[1].strip(" \n")
- queue_techs_unavailable = queue.findAll('td', {'class' : 'idle_status'})
- queue_techs_unavailable = len(queue_techs_unavailable)
- elif queue_url == CHATS_URL:
- # custom Chats-specific attributes
- ## remeber that while a chatter might be not be available, they may still be on active chat(s)
- ## only chatters that are both unnavailable and IDLE are not actively taking chats or with active customers
- queue_type = "chat"
- # find all chatters with a 'red' color class, indicating they are inactive
- queue_techs_logged_in = int(queue.find(text="Logged In To Chats").findNext('td').contents[0])
- count_techs_unavailable = int(len(queue.findAll('td', {'style' : 'white-space: nowrap;color:red'})))
- # count_techs_unavailable = len(queue_techs_unavailable)
- # collect IDLE status chatters and deduct from chatters with customers, since IDLE chatters have no customers
- queue_techs_idle = queue.findAll('td', {'class' : '_status'})
- ## count the number of IDLE chatters
- count_techs_idle = 0
- for i in queue_techs_idle:
- if i.contents[0] == "IDLE":
- count_techs_idle += 1
- # deduct IDLE chatters from from chatters with customers
- queue_techs_with_customers = queue_techs_logged_in - count_techs_idle
- # count the number of chatters both unnavailable and IDLE
- count_techs_available = 0
- # queue_techs_available = queue_techs_logged_in - queue_techs_idle
- queue_techs_available = queue_techs_logged_in - count_techs_unavailable
- # (self, queue_type, queue_id, queue_name, count_customers_in_queue, top_wait_time, avg_wait_time, count_techs_logged_in, count_techs_with_customers, count_techs_unavailable):
- call_queue = Queue(queue_type, queue_id, queue_name, queue_customers_waiting, queue_top_wait_time, queue_awt, queue_techs_logged_in, queue_techs_with_customers, count_techs_unavailable, queue_techs_available)
- #call_queue.displayAll()
- QUEUE_DATA.append(call_queue)
- # Generate usable report output
- def report_queues():
- #print SELECTED_QUEUES
- queue_count = len(SELECTED_QUEUES)
- #print "Total queues: ", queue_count
- count = 0
- ## while loop because we are using the order of tuples in SELECTED_QUEUES
- while (count < queue_count):
- queue_name = SELECTED_QUEUES[count]
- # print queue_name[0]
- for q in QUEUE_DATA:
- if q.name == queue_name[0]:
- output_autokey_values(q)
- count += 1
- def output_autokey_values(q):
- # print q.name
- #keyboard.send_keys(q.name + "<tab>")
- #print q.count_customers_in_queue
- keyboard.send_keys(q.count_customers_in_queue + "<tab>")
- if q.type == "call":
- #print q.avg_wait_time
- keyboard.send_keys(q.avg_wait_time + "<tab>")
- if q.name != "Level 3 Calls":
- #print q.count_techs_with_customers
- keyboard.send_keys(str(q.count_techs_with_customers) + "<tab>")
- if q.type == "chat":
- #print q.top_wait_time
- keyboard.send_keys(q.top_wait_time + "<tab>")
- #print q.count_techs_logged_in
- keyboard.send_keys(str(q.count_techs_logged_in) + "<tab>")
- if q.type == "chat":
- #print q.count_techs_available
- keyboard.send_keys(str(q.count_techs_available) + "<tab>")
- #keyboard.send_keys("<enter>")
- ## (TODO?: Google Doc cell population function?)
- ##### running
- if bh_login_check():
- #print "logged in. yay!"
- #print "scraping wallboards..."
- scrape_queues()
- if QUEUE_DATA:
- report_queues()
- else:
- print "Sorry, no queues collected to report."
Advertisement
Add Comment
Please, Sign In to add comment