我通过在线课程学习了几个月的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'])
答案 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}附加到foo
,foo
和bar
实际上也会引用相同的内容(因此更改内容会同时更改)。
如果您打算这样做,这是一个非常好的解决方案。但是,如果您打算将推文与不同的听众分开,那可能会让您头疼不已。我个人会这样构建我的课程:
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。
此类搜索中的所有关键字都是OR
,source:
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()