如何为股票数据爬取GUI程序添加无效股票代码错误提示?
Hey there, let's get that invalid stock ticker crash sorted out for your Python GUI scraper. The main issue right now is that when a bad ticker is entered, the code tries to access elements that don't exist on the page (like the price span), which throws an error and stops the program. Here's a step-by-step fix with updated code:
Key Fixes to Implement
- Add HTTP status code check: Verify if the request to Bloomberg returned a valid page (status code 200) — invalid tickers usually return a 404 or non-200 status.
- Check for element existence: Before accessing
.texton scraped elements, make sure they aren'tNone(since non-existent elements will return None). - Use try-except blocks: Catch unexpected errors (like connection issues) and show user-friendly messages.
- Add a GUI alert: Use Tkinter's
messageboxto pop up the "Please enter a valid stock ticker." message instead of crashing.
First, update your imports to include messagebox from Tkinter:
from tkinter import Tk, Frame, Label, Entry, Button, messagebox
Updated Calculation() Function
def Calculation(): try: lower_stock = Ticker_entry.get().strip() if not lower_stock: messagebox.showerror("Invalid Input", "Please enter a stock ticker.") return stock = lower_stock.upper() url = make_url(stock) page = requests.get(url) # Check if the page is valid (invalid tickers often return 404 or 403) if page.status_code != 200: messagebox.showerror("Invalid Ticker", "Please enter a valid stock ticker.") return soup = BeautifulSoup(page.content, "lxml") # Find current price with existence check current_number = soup.find('span', attrs={'class':'priceText__1853e8a5'}) if not current_number: messagebox.showerror("Invalid Ticker", "Please enter a valid stock ticker.") return current_price = current_number.text Stock_price_output.delete(0, END) # Clear previous content first Stock_price_output.insert(0, f"${current_price}") # Find opening price with existence check opening_number = soup.find('div', attrs={'class':'value__b93f12ea'}) if not opening_number: messagebox.showerror("Invalid Ticker", "Please enter a valid stock ticker.") return opening_price = opening_number.text Stock_price_day_output.delete(0, END) Stock_price_day_output.insert(0, f"${opening_price}") # Find last closing price with existence check closing_numbers = soup.find_all('div', attrs={'class':'value__b93f12ea'}) if len(closing_numbers) < 2: messagebox.showerror("Invalid Ticker", "Please enter a valid stock ticker.") return closing_number = closing_numbers[1] closing_price = closing_number.text Last_closing_price_output.delete(0, END) Last_closing_price_output.insert(0, f"${closing_price}") # Find news (fixed the incomplete line from your original code) news = soup.find_all('div', attrs={'class':'headline__07dbac92'}) # Clear previous news entries for entry in [Stock_news_output1, Stock_news_output2, Stock_news_output3]: entry.delete(0, END) if len(news) >= 2: news_1 = news[1].text Stock_news_output1.insert(0, news_1) if len(news) >=3: news_2 = news[2].text Stock_news_output2.insert(0, news_2) if len(news) >=4: news_3 = news[3].text Stock_news_output3.insert(0, news_3) except ConnectionError: messagebox.showerror("Connection Error", "Could not connect to the stock website. Please check your internet connection.") except Exception as e: # Catch-all for unexpected errors (you can log this if needed) messagebox.showerror("Error", f"An unexpected error occurred: {str(e)}")
Full Updated Code
import matplotlib import sys from requests.exceptions import ConnectionError import matplotlib.dates as dates from tkinter import Tk, Frame, Label, Entry, Button, messagebox from bs4 import BeautifulSoup import requests import lxml import datetime matplotlib.use("TkAgg") from matplotlib import pyplot as plt #Graphical User Interface #------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- root = Tk() root.title("Stock Price") root.configure(background="white") Calculator = Frame(root, height=300, width=700, bg="white").grid(column=0, row=2) title = Label(root, bg="white", text="Stock Price Calculator", font="Sans 25 bold", fg="black").grid(row=0) Stock_ticker = Label(root, text="Input stock ticker here:", font="Sans 18 bold") Stock_ticker.place(x=7, y=60) Ticker_entry = Entry(root, width=10) Ticker_entry.place(x=235, y=64) Stock_price = Label(root, text="Current stock price:", font="Sans 15") Stock_price.place(x=7, y=100) Stock_price_output = Entry(root, width=10) Stock_price_output.place(x=160, y=100) Stock_price_day = Label(root, text="Opening price for the day:", font="Sans 15") Stock_price_day.place(x=7, y=140) Stock_price_day_output = Entry(root, width=10) Stock_price_day_output.place(x=195, y=141) Last_closing_price = Label(root, text="Last closing price:", font="Sans 15") Last_closing_price.place(x=7, y=180) Last_closing_price_output = Entry(root, width=10) Last_closing_price_output.place(x=180, y=181) Stock_news = Label(root, text="News about stock:", font="Sans 15") Stock_news.place(x=7, y=220) Stock_news_output1 = Entry(root, width=50) Stock_news_output1.place(x=150, y=221) Stock_news_output2 = Entry(root, width=50) Stock_news_output2.place(x=150, y=242) Stock_news_output3 = Entry(root, width=50) Stock_news_output3.place(x=150, y=263) Submit = Button(root, text="Submit", font="Sans 14", command = lambda: Calculation()) Submit.place(x=165, y=300) Reset = Button(root, text="Reset", font="Sans 14", command = lambda: Cleaning(Ticker_entry, Stock_price_output, Stock_price_day_output, Last_closing_price_output, Stock_news_output1, Stock_news_output2, Stock_news_output3)) Reset.place(x=250, y=300) #------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- def make_url(ticker_symbol): #making a function that returns a URL when a ticker is passed through it return "https://www.bloomberg.com/quote/%s:US" % ticker_symbol def make_historical_url(ticker_symbol): return "https://www.nasdaq.com/symbol/%s/historical" % ticker_symbol def Cleaning(*entries): for entry in entries: entry.delete(0, END) def Calculation(): try: lower_stock = Ticker_entry.get().strip() if not lower_stock: messagebox.showerror("Invalid Input", "Please enter a stock ticker.") return stock = lower_stock.upper() url = make_url(stock) page = requests.get(url) # Check if the page is valid (invalid tickers often return 404 or 403) if page.status_code != 200: messagebox.showerror("Invalid Ticker", "Please enter a valid stock ticker.") return soup = BeautifulSoup(page.content, "lxml") # Find current price with existence check current_number = soup.find('span', attrs={'class':'priceText__1853e8a5'}) if not current_number: messagebox.showerror("Invalid Ticker", "Please enter a valid stock ticker.") return current_price = current_number.text Stock_price_output.delete(0, END) # Clear previous content first Stock_price_output.insert(0, f"${current_price}") # Find opening price with existence check opening_number = soup.find('div', attrs={'class':'value__b93f12ea'}) if not opening_number: messagebox.showerror("Invalid Ticker", "Please enter a valid stock ticker.") return opening_price = opening_number.text Stock_price_day_output.delete(0, END) Stock_price_day_output.insert(0, f"${opening_price}") # Find last closing price with existence check closing_numbers = soup.find_all('div', attrs={'class':'value__b93f12ea'}) if len(closing_numbers) < 2: messagebox.showerror("Invalid Ticker", "Please enter a valid stock ticker.") return closing_number = closing_numbers[1] closing_price = closing_number.text Last_closing_price_output.delete(0, END) Last_closing_price_output.insert(0, f"${closing_price}") # Find news (fixed the incomplete line from your original code) news = soup.find_all('div', attrs={'class':'headline__07dbac92'}) # Clear previous news entries for entry in [Stock_news_output1, Stock_news_output2, Stock_news_output3]: entry.delete(0, END) if len(news) >= 2: news_1 = news[1].text Stock_news_output1.insert(0, news_1) if len(news) >=3: news_2 = news[2].text Stock_news_output2.insert(0, news_2) if len(news) >=4: news_3 = news[3].text Stock_news_output3.insert(0, news_3) except ConnectionError: messagebox.showerror("Connection Error", "Could not connect to the stock website. Please check your internet connection.") except Exception as e: # Catch-all for unexpected errors (you can log this if needed) messagebox.showerror("Error", f"An unexpected error occurred: {str(e)}")
What This Does
- Empty Input Check: Catches when the user submits an empty ticker field.
- Status Code Check: Immediately flags invalid tickers if Bloomberg returns a non-200 page.
- Element Existence Checks: Makes sure every scraped element exists before trying to access its text, preventing
AttributeError. - Error Handling: Catches connection issues and other unexpected errors, showing clear messages instead of crashing.
- Clearing Previous Data: Deletes old content from input fields before inserting new data, so results don't pile up.
内容的提问来源于stack exchange,提问作者Leonardo Zapparoli
相关产品推荐
相关产品推荐

