如何通过tweepy保存json中的流媒体推文?

时间:2014-05-08 02:15:37

标签: python json tweepy

我通过在线课程学习了几个月的Python,并希望通过一个真实的迷你项目来进一步学习。

对于这个项目,我想从twitter流API收集推文并以json格式存储它们(虽然你可以选择保存关键信息,如status.text,status.id,我被告知最好的方法是保存所有数据并在之后进行处理。但是,通过添加on_data(),代码就不再起作用了。有人能帮忙吗?我也对有关存储/处理推文的最佳方式的建议持开放态度!我的最终目标是能够根据人口统计变量(例如,国家,用户资料年龄等)和特定品牌(例如Apple,HTC,Samsung)的情绪来跟踪推文。

此外,我还想尝试按位置和关键字过滤推文。我已经分别调整了How to add a location filter to tweepy module的代码。但是,虽然它在有少量关键字时有效,但在关键字数量增加时会停止。我认为我的代码效率低下。有没有更好的方法呢?

### code to save tweets in json###
import sys
import tweepy
import json

consumer_key=" "
consumer_secret=" "
access_key = " "
access_secret = " "

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_key, access_secret)
api = tweepy.API(auth)
file = open('today.txt', 'a')

class CustomStreamListener(tweepy.StreamListener):
    def on_status(self, status):
        print status.text

    def on_data(self, data):
        json_data = json.loads(data)
        file.write(str(json_data))

    def on_error(self, status_code):
        print >> sys.stderr, 'Encountered error with status code:', status_code
        return True # Don't kill the stream

    def on_timeout(self):
        print >> sys.stderr, 'Timeout...'
        return True # Don't kill the stream

sapi = tweepy.streaming.Stream(auth, CustomStreamListener())
sapi.filter(track=['twitter'])

3 个答案:

答案 0 :(得分:6)

我找到了将推文保存到json文件的方法。很高兴听到它如何改进!

# initialize blank list to contain tweets
tweets = []
# file name that you want to open is the second argument
save_file = open('9may.json', 'a')

class CustomStreamListener(tweepy.StreamListener):
    def __init__(self, api):
        self.api = api
        super(tweepy.StreamListener, self).__init__()

        self.save_file = tweets

    def on_data(self, tweet):
        self.save_file.append(json.loads(tweet))
        print tweet
        save_file.write(str(tweet))

答案 1 :(得分:5)

在重新阅读您的原始问题时,我意识到您提出了一些很多的小问题。我会尝试在这里回答大部分问题,但有些人可能真的要问一个单独的问题。

  • 为什么它会因添加 on_data 而中断?

没有看到实际的错误,很难说。它实际上对我不起作用,直到我重新生成我的消费者/访问密钥,我试试。

我可能做的一些事情与你的答案不同。

tweets是一份全球名单。这意味着如果您有多个StreamListeners(即在多个线程中), 任何流侦听器收集的每条推文都将添加到此列表中。这是因为Python中的列表引用了内存中的位置 - 如果这令人困惑,这里是我的意思的基本示例:

>>> bar = []
>>> foo = bar
>>> foo.append(7)
>>> print bar
[7]

请注意,即使您认为将{7}附加到foofoobar实际上也会引用相同的内容(因此更改内容会同时更改)。

如果您打算这样做,这是一个非常好的解决方案。但是,如果您打算将推文与不同的听众分开,那可能会让您头疼不已。我个人会这样构建我的课程:

class CustomStreamListener(tweepy.StreamListener):
    def __init__(self, api):
        self.api = api
        super(tweepy.StreamListener, self).__init__()

        self.list_of_tweets = []

这会将推文列表更改为仅在您的班级范围内。此外,我认为将属性名称从self.save_file更改为self.list_of_tweets是合适的,因为您还将要发送的{em>文件命名为save_file。虽然这不会严格地导致错误,但是对于我而言,self.save_file是列表而save_file是文件是令人困惑的。它可以帮助您和其他任何读取您的代码的人找出一切都在做什么。 More on variable naming.

在我的评论中,我提到你不应该使用file作为变量名。 file是一个Python内置函数,用于构造类型为file的新对象。你可以在技术上覆盖它,但这样做是一个非常糟糕的主意。有关更多内置版本,请参阅Python documentation

  • 如何过滤多个关键字的结果?

此类搜索中的所有关键字都是ORsource

sapi.filter(track=['twitter', 'python', 'tweepy'])

这意味着这将获得包含“twitter”,“python”或“tweepy”的推文。如果您想要联合(AND)所有条款,则必须通过根据您要搜索的所有术语列表检查推文进行后期处理。

  • 如何根据地理位置和关键字过滤结果?

我实际上刚刚意识到你按照我的建议做了ask this as its own question。正则表达式后处理解决方案是实现此目的的好方法。您也可以尝试按位置关键字进行过滤,如下所示:

sapi.filter(locations=[103.60998,1.25752,104.03295,1.44973], track=['twitter'])
  • 存储/处理推文的最佳方式是什么?

这取决于你将收集多少。我是数据库的粉丝,特别是如果你打算在很多推文上做一个情绪分析。收集数据时,您应该收集您需要的内容。这意味着,当您将结果保存到数据库/ on_data方法中的任何位置时,您应该从JSON中提取重要部分而不保存任何其他内容。例如,如果您想看品牌,国家和时间,只需要考虑这三件事;不要保存推文的整个JSON转储,因为它只会占用不必要的空间。

答案 2 :(得分:1)

我只是将原始JSON插入数据库。它似乎有点丑陋和hacky但它​​确实有效。一个值得注意的问题是推文的创建日期存储为字符串。 How do I compare dates from Twitter data stored in MongoDB via PyMongo?提供了一种解决方法(我在代码中插入注释以指示执行该任务的位置)

# ...

client = pymongo.MongoClient()
db = client.twitter_db
twitter_collection = db.tweets

# ...

class CustomStreamListener(tweepy.StreamListener):
    # ...
    def on_status(self, status):
            try:
                twitter_json = status._json
                # TODO: Transform created_at to Date objects before insertion
                tweet_id = twitter_collection.insert(twitter_json)
            except:
                # Catch any unicode errors while printing to console
                # and just ignore them to avoid breaking application.
                pass
    # ...

stream = tweepy.Stream(auth, CustomStreamListener(), timeout=None, compression=True)
stream.sample()