import requests from bs4 import BeautifulSoup ''' Amazon alexa skill to grab stock data from yahoo finance and present data to user Currently has database of ~10 companies Future updates to include database of all S&P 500 companies if data size allows ''' ################################################################## def lambda_handler(event, context): #Checks to make sure application id is same as alexa skill (links) if (event['session']['application']['applicationId'] != #Change to application id listed under your alexa skill in the developer portal "amzn1.ask.skill.XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"): raise ValueError("Invalid Application ID") if event["session"]["new"]: on_session_started({"requestId": event["request"]["requestId"]}, event["session"]) #check event types and call appropriate response if event["request"]["type"] == "LaunchRequest": return on_launch(event["request"], event["session"]) elif event["request"]["type"] == "IntentRequest": return on_intent(event["request"], event["session"]) elif event["request"]["type"] == "SessionEndedRequest": return on_session_ended(event["request"], event["session"]) ################################################################## def on_session_started(session_started_request, session): print "Starting new." ################################################################## def on_launch(launch_request, session): return get_welcome_response() ################################################################## def on_intent(intent_request, session): intent = intent_request["intent"] intent_name = intent_request["intent"]["name"] if intent_name == "GetCurrentPrice": return get_current_price(intent) elif intent_name == "GetHigh": return get_high(intent) elif intent_name == "GetLow": return get_low(intent) elif intent_name == "AMAZON.HelpIntent": return get_welcome_response() elif intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent": return handle_session_end_request() else: raise ValueError("Invalid intent") ################################################################## def on_session_ended(session_ended_request, session): print "Ending session." ################################################################## def handle_session_end_request(): card_title = "Stocker" speech_output = "Im sorry dave. Im afraid I cant do that." should_end_session = True return build_response({}, build_speechlet_response(card_title, speech_output, None, should_end_session)) ################################################################## def get_welcome_response(): #Response to user invoking stock app without parameters/intents session_attributes = {} card_title = "Stocker" speech_output = "Welcome to the Stocker skill. " \ "You can ask me for current stock prices, or " \ "ask me about stock highs and lows." reprompt_text = "Please ask me for stock prices, " \ "for example Apple stock price." should_end_session = False return build_response(session_attributes, build_speechlet_response( card_title, speech_output, reprompt_text, should_end_session)) ################################################################## def find_availability(to_find, restaurant): page = requests.get("") page_data = BeautifulSoup(page.content, "html.parser") ################################################################## def grab_data(to_find, ticker_code): if ticker_code != "EVRGRN": #send http response fro yahoo finance to grab data based on passed in ticker code page = requests.get("https://finance.yahoo.com/quote/" + ticker_code + "?p=" + ticker_code) #resolves the page content into its component parts data = BeautifulSoup(page.content, "html.parser") if to_find == "get_current_price": #grab text from appropriate class and return to current object current = data.find(class_ = "Fw(b) Fz(36px) Mb(-4px)").get_text() #find index of decimal point to seperate dollars from cents index = current.index('.') dollars = current[:index] cents = current[index+1:] #map each component in list to a string object, and join via str operator (in this case nothing, so it joins together) dollars = ''.join(map(str, dollars)) cents = ''.join(map(str, cents)) return dollars + " dollars and " + cents + " cents" elif to_find == "get_high" or to_find =="get_low": classes= data.find_all(class_ = "Ta(end) Fw(b)") #several stock values are listed under the class with the given value, so #we grab fourth object in list of classes, returning stock range stock_range = list(classes[4].get_text()) #since text we grab is not in unicode, we grab each str object and encode it with UTF8 stock_range = [x.encode('UTF8') for x in stock_range] if to_find == "get_high": high = "" for letter in stock_range: #since returned list of str objects are a range from low to high (e.g. $$ - $$), we grab second half of data for high value if letter == '-': high = stock_range[stock_range.index(letter)+2:] index = high.index('.') dollars = high[:index] cents = high[index+1:] #map each component in list to a string object, and join via str operator (in this case nothing, so it joins together) dollars = ''.join(map(str, dollars)) cents = ''.join(map(str, cents)) return dollars + " dollars and" + cents + " cents" elif to_find == "get_low": low = "" for letter in stock_range: #since returned list of str objects are a range from high to low (e.g. $$-$$), we grab first half of data for low value if letter == '-': low = stock_range[:stock_range.index(letter)-1] index = low.index('.') dollars = low[:index] cents = low[index+1:] #map each component in list to a string object, and join via str operator (in this case nothing, so it joins together) dollars = ''.join(map(str, dollars)) cents = ''.join(map(str, cents)) return dollars + " dollars and " + cents + " cents" #cor is on its way else: if to_find == "get_current_price": return "over 9000" elif to_find == "get_high" or to_find =="get_low": return "not yet available. Please ask Tristan" ################################################################## def get_current_price(intent): session_attributes = {} card_title = "Current Stock Price" speech_output = "I'm not sure which company you wanted stock prices for. " \ "Please try again." reprompt_text = "I'm not sure which company you wanted stock prices for. " \ "Please try again." should_end_session = False if "Ticker" in intent["slots"]: ticker_name = intent["slots"]["Ticker"]["value"] #grab appropriate value based on name from ticke code dict ticker_code = get_ticker_code(ticker_name.lower()) if (ticker_code != "unkn"): card_title = "Current price for " + ticker_name.title() price = grab_data(get_current_price.__name__, ticker_code) speech_output = "Current price for " + ticker_name + " is: " + price reprompt_text = "" should_end_session = True return build_response(session_attributes, build_speechlet_response( card_title, speech_output, reprompt_text, should_end_session)) ################################################################## def get_high(intent): session_attributes = {} card_title = "Stock High" speech_output = "I'm not sure which company you wanted stock prices for. " \ "Please try again." reprompt_text = "I'm not sure which company you wanted stock prices for. " \ "Please try again." should_end_session = False if "Ticker" in intent["slots"]: ticker_name = intent["slots"]["Ticker"]["value"] #grab appropriate value based on name from ticke code dict ticker_code = get_ticker_code(ticker_name.lower()) if (ticker_code != "unkn"): card_title = "High price for " + ticker_name.title() price = grab_data(get_high.__name__, ticker_code) speech_output = "Stock high for " + ticker_name + " is: " + price reprompt_text = "" should_end_session = True return build_response(session_attributes, build_speechlet_response( card_title, speech_output, reprompt_text, should_end_session)) ################################################################## def get_low(intent): session_attributes = {} card_title = "Stock Low" speech_output = "I'm not sure which company you wanted stock prices for. " \ "Please try again." reprompt_text = "I'm not sure which company you wanted stock prices for. " \ "Please try again." should_end_session = False if "Ticker" in intent["slots"]: ticker_name = intent["slots"]["Ticker"]["value"] #grab appropriate value based on name from ticke code dict ticker_code = get_ticker_code(ticker_name.lower()) if (ticker_code != "unkn"): card_title = "Low price for " + ticker_name.title() price = grab_data(get_low.__name__, ticker_code) speech_output = "Stock low for " + ticker_name + " is: " + price reprompt_text = "" should_end_session = True return build_response(session_attributes, build_speechlet_response( card_title, speech_output, reprompt_text, should_end_session)) ################################################################## def build_speechlet_response(title, output, reprompt_text, should_end_session): #return data in json format to alexa skills kit return { "outputSpeech": { "type": "PlainText", "text": output }, "card": { "type": "Simple", "title": title, "content": output }, "reprompt": { "outputSpeech": { "type": "PlainText", "text": reprompt_text } }, "shouldEndSession": should_end_session } ################################################################## def get_ticker_code(ticker_name): #function to grab associated value based on ticker_name parameter return{ 'alphabet': 'GOOGL', 'apple': 'AAPL', 'amazon':'AMZN', 'tesla':'TSLA', 'oracle':'ORCL', 'irobot':'IRBT', 'microsoft':'MSFT', 'facebook':'FB', 'intel':'INTC', 'ibm':'IBM', 'evergreen robotics': 'EVRGRN', 'netflix':'NFLX' }.get(ticker_name, "unkn") ################################################################## def build_response(session_attributes, speechlet_response): return { "version": "1.0", "sessionAttributes": session_attributes, "response": speechlet_response }