Tweepy / Python hängt

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Chris_we
User
Beiträge: 1
Registriert: Freitag 1. Mai 2020, 07:54

Hallo, ich möchte einen Twitter-Bot programmieren. Bei meinem Script wird aber nicht ausgeführt. Das Problem sehe ich leider nicht
Code:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-
from tweepy.streaming import StreamListener
from tweepy import OAuthHandler
from tweepy import Stream
 
import twitter_credentials
 
# # # # TWITTER STREAMER # # # #
class TwitterStreamer():
    """
    Class for streaming and processing live tweets.
    """
    def __init__(self):
        pass

    def stream_tweets(self, fetched_tweets_filename, hash_tag_list):
        # This handles Twitter authetification and the connection to Twitter Streaming API
        listener = StdOutListener(fetched_tweets_filename)
        auth = OAuthHandler(twitter_credentials.CONSUMER_KEY, twitter_credentials.CONSUMER_SECRET)
        auth.set_access_token(twitter_credentials.ACCESS_TOKEN, twitter_credentials.ACCESS_TOKEN_SECRET)
        stream = Stream(auth, listener)

        # This line filter Twitter Streams to capture data by the keywords: 
        stream.filter(track=hash_tag_list)


# # # # TWITTER STREAM LISTENER # # # #
class StdOutListener(StreamListener):
    """
    This is a basic listener that just prints received tweets to stdout.
    """
    def __init__(self, fetched_tweets_filename):
        self.fetched_tweets_filename = fetched_tweets_filename

    def on_data(self, data):
        try:
            print(data)
            with open(self.fetched_tweets_filename, 'a') as tf:
                tf.write(data)
            return True
        except BaseException as e:
            print("Error on_data %s" % str(e))
        return True
          

    def on_error(self, status):
        print(status)

 
if __name__ == '__main__':
 
    # Authenticate using config.py and connect to Twitter Streaming API.
    hash_tag_list = ["#besserbeideeltern"]
    fetched_tweets_filename = "tweets.txt"

    twitter_streamer = TwitterStreamer()
    twitter_streamer.stream_tweets(fetched_tweets_filename, hash_tag_list)
Ich nutze ubuntu. Wenn ich den Prozess abbreche, kommt folgender Hinweis:
^CTraceback (most recent call last):
File "tweepy_streamer.py", line 58, in <module>
twitter_streamer.stream_tweets(fetched_tweets_filename, hash_tag_list)
File "tweepy_streamer.py", line 25, in stream_tweets
stream.filter(track=hash_tag_list)
File "/home/admin/.local/lib/python3.6/site-packages/tweepy/streaming.py", line 474, in filter
self._start(is_async)
File "/home/admin/.local/lib/python3.6/site-packages/tweepy/streaming.py", line 389, in _start
self._run()
File "/home/admin/.local/lib/python3.6/site-packages/tweepy/streaming.py", line 289, in _run
self._read_loop(resp)
File "/home/admin/.local/lib/python3.6/site-packages/tweepy/streaming.py", line 339, in _read_loop
line = buf.read_line()
File "/home/admin/.local/lib/python3.6/site-packages/tweepy/streaming.py", line 200, in read_line
self._buffer += self._stream.read(self._chunk_size)
File "/home/admin/.local/lib/python3.6/site-packages/urllib3/response.py", line 444, in read
data = self._fp.read(amt)
File "/usr/lib/python3.6/http/client.py", line 459, in read
n = self.readinto(b)
File "/usr/lib/python3.6/http/client.py", line 493, in readinto
return self._readinto_chunked(b)
File "/usr/lib/python3.6/http/client.py", line 588, in _readinto_chunked
chunk_left = self._get_chunk_left()
File "/usr/lib/python3.6/http/client.py", line 556, in _get_chunk_left
chunk_left = self._read_next_chunk_size()
File "/usr/lib/python3.6/http/client.py", line 516, in _read_next_chunk_size
line = self.fp.readline(_MAXLINE + 1)
File "/usr/lib/python3.6/socket.py", line 586, in readinto
return self._sock.recv_into(b)
File "/usr/lib/python3.6/ssl.py", line 1012, in recv_into
return self.read(nbytes, buffer)
File "/usr/lib/python3.6/ssl.py", line 874, in read
return self._sslobj.read(len, buffer)
File "/usr/lib/python3.6/ssl.py", line 631, in read
v = self._sslobj.read(len, buffer)


Mit einem anderen Script funtioniert es:

Code: Alles auswählen

import tweepy

#Add your credentials here
twitter_keys = {
        'consumer_key':        '',
        'consumer_secret':     '',
        'access_token_key':    '',
        'access_token_secret': '
    }

#Setup access to API
auth = tweepy.OAuthHandler(twitter_keys['consumer_key'], twitter_keys['consumer_secret'])
auth.set_access_token(twitter_keys['access_token_key'], twitter_keys['access_token_secret'])

api = tweepy.API(auth)

#Make call on home timeline, print each tweets text
public_tweets = api.home_timeline()
for tweet in public_tweets:
    print(tweet.text)
kann mir da jmd auf die Sprünge helfen?
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Den eigentlichen Fehler hast du jetzt vergessen zu kopieren, da kann man dann natürlich wenig sehen. Scheint irgend einen Fehler mit der Verbindung zu geben.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Chris_we: Der Code im ``if __name__ …``-Zweig sollte in einer Funktion stehen damit keine modulglobalen Variablen definiert werden.

`TwitterStreamer` ist als Klasse unsinnig weil das keine Klasse ist wenn man eine leere `__init__()` und *eine* ”Methode” hat die das Objekt selbst gar nicht verwendet. Das ist einfach eine umständlich geschriebene Funktion.

Kommentare sollten nicht falsch sein. Das ist schlimmer als gar keine Kommentare. Es gibt keine `config.py`, die heisst hier `twitter_credentials.py`.

Auch Docstrings sollte inhaltlich stimmen, genau wie Namen. Der `StdOutListener` soll anscheinend doch mehr machen als einfach nur auf `sys.stdout` auszugeben.

In der Klasse gibt's dann auch Fehler. Die `__init__()` der Basisklasse wird nicht aufgerufen, das ist aber wichtig damit die Klasse vollständig initialisiert wird.

Das nächste Problem ist dann die `on_data()`-Methode, wo auch die von der Basisklasse einfach so komplett ersetzt wird. `on_error()` kann dann aber niemals aufgerufen werden, weil das genau die originale `on_data()`-Methode macht, die die rohen Daten bekommt und parst und dann entsprechend eine der anderen `on_*()`-Methoden aufruft.

Wenn man da die rohen Daten abgreifen und speichern will, muss man trotzdem die weitere Verarbeitung noch aufrufen. Ich weiss nicht was man da bekommt, Zeichenkette oder Bytes, also muss man die Datei eventuell noch im Binärmodus öffnen. Sollten es Zeichenketten sein, sollte man noch UTF-8 als Kodierung angeben.

`on_error()` sollte dann auch `False` zurückgeben, sonst läuft es bei Fehlern weiter, was ja nicht geht, und wieder zu Fehlern führt, aber weiterläuft, was ja nicht geht, und…

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
from tweepy import OAuthHandler, Stream
from tweepy.streaming import StreamListener

import twitter_credentials


class Listener(StreamListener):
    """
    This is a basic listener that just prints received data and saves it into a
    file.
    """

    def __init__(self, fetched_tweets_filename):
        StreamListener.__init__(self)
        self.fetched_tweets_filename = fetched_tweets_filename

    def on_data(self, raw_data):
        try:
            print(raw_data)
            with open(
                self.fetched_tweets_filename, "a", encoding="utf-8"
            ) as file:
                file.write(raw_data)
        except Exception as error:
            print("Error on_data", ascii(error))
        
        return StreamListener.on_data(self, raw_data)

    def on_error(self, status_code):
        print(status_code)
        return False


def stream_tweets(fetched_tweets_filename, hash_tag_list):
    #
    # This handles Twitter authetification and the connection to Twitter
    # Streaming API.
    #
    auth = OAuthHandler(
        twitter_credentials.CONSUMER_KEY, twitter_credentials.CONSUMER_SECRET
    )
    auth.set_access_token(
        twitter_credentials.ACCESS_TOKEN,
        twitter_credentials.ACCESS_TOKEN_SECRET,
    )
    stream = Stream(auth, Listener(fetched_tweets_filename))
    #
    # This line filter Twitter Streams to capture data by the keywords:
    #
    stream.filter(track=hash_tag_list)


def main():
    hash_tag_list = ["#besserbeideeltern"]
    fetched_tweets_filename = "tweets.txt"
    stream_tweets(fetched_tweets_filename, hash_tag_list)


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten