使用Tweepy Stream拉取Twitter推文,Tkinter GUI无法显示多条推文求助
Hey there! Let's figure out why your Tkinter setup isn't showing multiple tweets properly. The main issues in your code are how you're creating the GUI window and handling incoming tweets—let's break this down and fix it step by step.
Problem Breakdown
Right now, every time a tweet comes in via on_data, you're creating a brand new Tk() root window and starting a new mainloop(). That means each tweet opens a separate window, and the first window's mainloop blocks the rest of the code from running until you close it. Plus, you're passing a tuple directly to the Label, which won't format the tweet nicely.
We need a persistent GUI that updates with new tweets, not a new window for every tweet.
Fixed Code
Here's a revised version of your code that addresses these issues:
import json import time import threading from tkinter import Tk, Text, Scrollbar, Frame from tweepy import Stream from tweepy import OAuthHandler from tweepy.streaming import StreamListener # Fill in your credentials here consumer_key = '' consumer_secret = '' access_token = '' access_secret = '' class TweetStreamListener(StreamListener): def __init__(self, text_widget, time_limit=30): self.start_time = time.time() self.limit = time_limit self.text_widget = text_widget # Reference to our GUI text display self.save_file = open('TwitterStream.json', 'a') super().__init__() def on_data(self, data): if (time.time() - self.start_time) < self.limit: # Parse the tweet data filtered = json.loads(data) screen_name = filtered['user']['screen_name'] # Clean up the text (decode byte string to regular string) tweet_text = filtered['text'].encode('ascii', 'ignore').decode('ascii') # Format the tweet for display display_text = f"@{screen_name}: {tweet_text}\n{'='*50}\n" # Update the GUI safely (Tkinter requires main thread updates) self.text_widget.after(0, self.update_display, display_text) # Save to files self.save_file.write(data) self.save_file.write('\n') return True else: self.save_file.close() return False def update_display(self, text): # Insert the new tweet at the end of the text widget self.text_widget.insert('end', text) # Auto-scroll to the latest tweet self.text_widget.see('end') def on_error(self, status): print(f"Error: {status}") def start_stream(text_widget): auth = OAuthHandler(consumer_key, consumer_secret) auth.set_access_token(access_token, access_secret) stream = Stream(auth, TweetStreamListener(text_widget, time_limit=30)) # Filter for whatever keywords you want here stream.filter(track=['python']) if __name__ == "__main__": # Initialize the main GUI window root = Tk() root.title("Twitter Stream Viewer") # Create a scrollable Text widget for displaying tweets frame = Frame(root) scrollbar = Scrollbar(frame) tweet_display = Text(frame, wrap='word', yscrollcommand=scrollbar.set, height=20, width=80) scrollbar.config(command=tweet_display.yview) tweet_display.pack(side='left', fill='both', expand=True) scrollbar.pack(side='right', fill='y') frame.pack(fill='both', expand=True, padx=10, pady=10) # Run the Tweepy stream in a separate thread (so it doesn't freeze the GUI) stream_thread = threading.Thread(target=start_stream, args=(tweet_display,)) stream_thread.daemon = True # Thread closes when main window closes stream_thread.start() # Start the GUI main loop root.mainloop()
Key Changes Explained
- Persistent GUI Window: We initialize the Tk root and Text widget once at the start, not per tweet. The Text widget is ideal for showing multiple lines of text with scrolling support.
- Threaded Stream: The Tweepy Stream runs in a separate thread. Its
filter()method is blocking, so running it in the main thread would freeze the GUI. - Safe GUI Updates: We use
after(0, ...)to schedule updates to the Text widget. Tkinter components can only be modified from the main thread, so this ensures we don't run into errors. - Cleaner Text Display: We decode the byte string back to a regular string and format each tweet with a separator line for readability.
- Auto-Scroll: The
see('end')call makes the widget automatically scroll to the latest tweet.
内容的提问来源于stack exchange,提问作者WilliamBeech

