大数据案例:MongoDB存储推特数据及可视化分析
1. 引言
在大数据时代,如何高效地存储和分析海量数据是一个关键问题。本文将介绍如何使用MongoDB存储推特数据,并通过Folium库将数据可视化展示在地图上。
2. 环境准备
在开始之前,我们需要完成以下准备工作:
1. 配置MongoDB Atlas集群,并获取连接字符串。
2. 准备好Twitter API的认证信息,包括
consumer_key
、
consumer_secret
、
access_token
和
access_token_secret
。
3. 准备好
senators.csv
文件,该文件包含美国参议员的相关信息。
4. 准备好
state_codes.py
文件,该文件包含美国各州的代码和全称的映射关系。
5. 准备好
keys.py
文件,用于存储各种API的密钥。
3. 数据处理流程
下面是整个数据处理的流程图:
graph LR
A[获取连接字符串] --> B[认证Twitter API]
B --> C[加载参议员数据]
C --> D[配置MongoClient]
D --> E[设置推特流]
E --> F[启动推特流]
F --> G[存储推特数据]
G --> H[统计每位参议员的推特数量]
H --> I[获取各州位置信息]
I --> J[按州分组推特数量]
J --> K[创建地图]
K --> L[创建热力图]
L --> M[创建地图标记]
M --> N[保存地图]
4. 详细步骤
4.1 认证Twitter API
使用Tweepy库进行Twitter API的认证:
import tweepy, keys
auth = tweepy.OAuthHandler(
keys.consumer_key, keys.consumer_secret)
auth.set_access_token(keys.access_token,
keys.access_token_secret)
api = tweepy.API(auth, wait_on_rate_limit=True,
wait_on_rate_limit_notify=True)
4.2 加载参议员数据
使用pandas库加载
senators.csv
文件,并将
TwitterID
列转换为字符串类型:
import pandas as pd
senators_df = pd.read_csv('senators.csv')
senators_df['TwitterID'] = senators_df['TwitterID'].astype(str)
pd.options.display.max_columns = 6
查看数据的前几行:
senators_df.head()
输出结果如下:
| State | Name | Party | TwitterHandle | TwitterID |
| — | — | — | — | — |
| AL | Richard Shelby | R | SenShelby | 21111098 |
| AL | Doug Jomes | D | SenDougJones | 941080085121175552 |
| AK | Lisa Murkowski | R | lisamurkowski | 18061669 |
| AK | Dan Sullivan | R | SenDanSullivan | 2891210047 |
| AZ | Jon Kyl | R | SenJonKyl | 24905240 |
4.3 配置MongoClient
使用pymongo库连接到MongoDB Atlas集群,并获取
senators
数据库:
from pymongo import MongoClient
atlas_client = MongoClient(keys.mongo_connection_string)
db = atlas_client.senators
4.4 设置推特流
指定要下载的推特数量,并创建
TweetListener
对象:
from tweetlistener import TweetListener
tweet_limit = 10000
twitter_stream = tweepy.Stream(api.auth,
TweetListener(api, db, tweet_limit))
4.5 启动推特流
使用
filter
方法启动推特流,跟踪参议员的
TwitterHandle
和
TwitterID
:
twitter_stream.filter(track=senators_df.TwitterHandle.tolist(),
follow=senators_df.TwitterID.tolist())
4.6 TweetListener类
TweetListener
类用于处理接收到的推特数据,并将其存储到MongoDB中:
# tweetlistener.py
"""TweetListener downloads tweets and stores them in MongoDB."""
import json
import tweepy
class TweetListener(tweepy.StreamListener):
"""Handles incoming Tweet stream."""
def __init__(self, api, database, limit=10000):
"""Create instance variables for tracking number of tweets."""
self.db = database
self.tweet_count = 0
self.TWEET_LIMIT = limit # 10,000 by default
super().__init__(api) # call superclass's init
def on_connect(self):
"""Called when your connection attempt is successful, enabling
you to perform appropriate application tasks at that point."""
print('Successfully connected to Twitter\n')
def on_data(self, data):
"""Called when Twitter pushes a new tweet to you."""
self.tweet_count += 1 # track number of tweets processed
json_data = json.loads(data) # convert string to JSON
self.db.tweets.insert_one(json_data) # store in tweets collection
print(f' Screen name: {json_data["user"]["name"]}')
print(f' Created at: {json_data["created_at"]}')
print(f'Tweets received: {self.tweet_count}')
# if TWEET_LIMIT is reached, return False to terminate streaming
return self.tweet_count != self.TWEET_LIMIT
def on_error(self, status):
print(status)
return True
4.7 统计每位参议员的推特数量
创建一个文本索引,然后统计包含每位参议员
TwitterHandle
的推特数量:
db.tweets.create_index([('$**', 'text')])
tweet_counts = []
for senator in senators_df.TwitterHandle:
tweet_counts.append(db.tweets.count_documents(
{"$text": {"$search": senator}}))
tweet_counts_df = senators_df.assign(Tweets=tweet_counts)
tweet_counts_df.sort_values(by='Tweets',
ascending=False).head(10)
输出结果如下:
| State | Name | Party | TwitterHandle | TwitterID | Tweets |
| — | — | — | — | — | — |
| SC | Lindsey Graham | R | LindseyGrahamSC | 432895323 | 1405 |
| MA | Elizabeth Warren | D | SenWarren | 970207298 | 1249 |
| CA | Dianne Feinstein | D | SenFeinstein | 476256944 | 1079 |
| HI | Brian Schatz | D | brianschatz | 47747074 | 934 |
| NY | Chuck Schumer | D | SenSchumer | 17494010 | 811 |
| IL | Tammy Duckworth | D | SenDuckworth | 1058520120 | 656 |
| CT | Richard Blumenthal | D | SenBlumenthal | 278124059 | 646 |
| HI | Mazie Hirono | D | maziehirono | 92186819 | 628 |
| UT | Orrin Hatch | R | SenOrrinHatch | 262756641 | 506 |
| RI | Sheldon Whitehouse | D | SenWhitehouse | 242555999 | 350 |
4.8 获取各州位置信息
使用
geopy
库获取各州的经纬度信息:
from geopy import OpenMapQuest
import time
from state_codes import state_codes
geo = OpenMapQuest(api_key=keys.mapquest_key)
states = tweet_counts_df.State.unique()
states.sort()
locations = []
for state in states:
processed = False
delay = .1
while not processed:
try:
locations.append(
geo.geocode(state_codes[state] + ', USA'))
print(locations[-1])
processed = True
except: # timed out, so wait before trying again
print('OpenMapQuest service timed out. Waiting.')
time.sleep(delay)
delay += .1
4.9 按州分组推特数量
使用pandas的
groupby
方法按州分组,并计算每个州的推特总数:
tweets_counts_by_state = tweet_counts_df.groupby(
'State', as_index=False).sum()
tweets_counts_by_state.head()
输出结果如下:
| State | Tweets |
| — | — |
| AK | 27 |
| AL | 2 |
| AR | 47 |
| AZ | 47 |
| CA | 1135 |
4.10 创建地图
使用Folium库创建地图:
import folium
usmap = folium.Map(location=[39.8283, -98.5795],
zoom_start=4, detect_retina=True,
tiles='Stamen Toner')
4.11 创建热力图
使用
Choropleth
方法创建热力图,根据每个州的推特数量对地图进行着色:
choropleth = folium.Choropleth(
geo_data='us-states.json',
name='choropleth',
data=tweets_counts_by_state,
columns=['State', 'Tweets'],
key_on='feature.id',
fill_color='YlOrRd',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='Tweets by State'
).add_to(usmap)
layer = folium.LayerControl().add_to(usmap)
4.12 创建地图标记
为每个州创建地图标记,并显示该州参议员的信息:
sorted_df = tweet_counts_df.sort_values(
by='Tweets', ascending=False)
for index, (name, group) in enumerate(sorted_df.groupby('State')):
strings = [state_codes[name]] # used to assemble popup text
for s in group.itertuples():
strings.append(
f'{s.Name} ({s.Party}); Tweets: {s.Tweets}')
text = '<br>'.join(strings)
marker = folium.Marker(
(locations[index].latitude, locations[index].longitude),
popup=text)
marker.add_to(usmap)
4.13 保存地图
将地图保存为HTML文件:
usmap.save('SenatorsTweets.html')
5. 总结
通过以上步骤,我们成功地将推特数据存储到MongoDB中,并使用Folium库将数据可视化展示在地图上。这种方法可以帮助我们更好地理解和分析数据,发现数据中的规律和趋势。同时,我们还可以进一步扩展这个案例,例如使用情感分析技术对推特数据进行情感分析,以了解公众对参议员的态度。
大数据案例:MongoDB存储推特数据及可视化分析
6. 关键技术点分析
6.1 MongoDB的使用
-
连接配置
:使用
pymongo库的MongoClient连接到MongoDB Atlas集群,通过传入集群的连接字符串实现连接。代码如下:
from pymongo import MongoClient
atlas_client = MongoClient(keys.mongo_connection_string)
db = atlas_client.senators
-
数据存储
:将推特的JSON数据作为文档存储在MongoDB的
tweets集合中。在TweetListener类的on_data方法中,使用insert_one方法将JSON对象插入到集合中。
def on_data(self, data):
self.tweet_count += 1
json_data = json.loads(data)
self.db.tweets.insert_one(json_data)
# 其他代码...
-
文本索引与搜索
:为了进行全文搜索,需要为
tweets集合创建文本索引。使用create_index方法创建索引后,使用count_documents方法统计包含特定文本的文档数量。
db.tweets.create_index([('$**', 'text')])
tweet_counts = []
for senator in senators_df.TwitterHandle:
tweet_counts.append(db.tweets.count_documents(
{"$text": {"$search": senator}}))
6.2 Tweepy库的使用
-
认证
:使用Tweepy库进行Twitter API的认证,通过
OAuthHandler和set_access_token方法设置认证信息。
import tweepy, keys
auth = tweepy.OAuthHandler(
keys.consumer_key, keys.consumer_secret)
auth.set_access_token(keys.access_token,
keys.access_token_secret)
api = tweepy.API(auth, wait_on_rate_limit=True,
wait_on_rate_limit_notify=True)
-
推特流
:使用
Stream类创建推特流,并通过filter方法指定跟踪的关键词和用户ID。
from tweetlistener import TweetListener
tweet_limit = 10000
twitter_stream = tweepy.Stream(api.auth,
TweetListener(api, db, tweet_limit))
twitter_stream.filter(track=senators_df.TwitterHandle.tolist(),
follow=senators_df.TwitterID.tolist())
6.3 Folium库的使用
-
地图创建
:使用
folium.Map方法创建地图,并设置初始位置、缩放级别和地图样式。
import folium
usmap = folium.Map(location=[39.8283, -98.5795],
zoom_start=4, detect_retina=True,
tiles='Stamen Toner')
-
热力图创建
:使用
Choropleth方法创建热力图,根据各州的推特数量对地图进行着色。
choropleth = folium.Choropleth(
geo_data='us-states.json',
name='choropleth',
data=tweets_counts_by_state,
columns=['State', 'Tweets'],
key_on='feature.id',
fill_color='YlOrRd',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='Tweets by State'
).add_to(usmap)
- 地图标记创建 :为每个州创建地图标记,并显示该州参议员的信息。
sorted_df = tweet_counts_df.sort_values(
by='Tweets', ascending=False)
for index, (name, group) in enumerate(sorted_df.groupby('State')):
strings = [state_codes[name]]
for s in group.itertuples():
strings.append(
f'{s.Name} ({s.Party}); Tweets: {s.Tweets}')
text = '<br>'.join(strings)
marker = folium.Marker(
(locations[index].latitude, locations[index].longitude),
popup=text)
marker.add_to(usmap)
7. 可能遇到的问题及解决方案
7.1 Twitter API速率限制
- 问题描述 :Twitter API有速率限制,如果请求过于频繁,会导致请求被拒绝。
-
解决方案
:在创建
API对象时,设置wait_on_rate_limit=True和wait_on_rate_limit_notify=True,让Tweepy在达到速率限制时自动等待,并在等待时发出通知。
api = tweepy.API(auth, wait_on_rate_limit=True,
wait_on_rate_limit_notify=True)
7.2 OpenMapQuest服务超时
-
问题描述
:在使用
geopy的OpenMapQuest服务获取各州位置信息时,可能会出现服务超时的情况。 -
解决方案
:使用
try-except语句捕获异常,并在超时后等待一段时间再重试,每次等待时间逐渐增加。
for state in states:
processed = False
delay = .1
while not processed:
try:
locations.append(
geo.geocode(state_codes[state] + ', USA'))
print(locations[-1])
processed = True
except: # timed out, so wait before trying again
print('OpenMapQuest service timed out. Waiting.')
time.sleep(delay)
delay += .1
8. 扩展与优化建议
8.1 情感分析
可以使用自然语言处理技术对推特数据进行情感分析,了解公众对参议员的态度是积极、消极还是中立。可以使用如
TextBlob
或
VADER
等库进行情感分析。
8.2 实时更新
可以将整个流程封装成一个定时任务,定期获取新的推特数据,并更新地图和统计信息,实现实时数据展示。
8.3 数据可视化优化
可以进一步优化地图的显示效果,例如添加更多的交互元素,如鼠标悬停显示详细信息、不同的地图样式等。
9. 总结回顾
本文详细介绍了如何使用MongoDB存储推特数据,并通过Folium库将数据可视化展示在地图上。整个流程包括Twitter API认证、数据加载、MongoDB连接与数据存储、推特流监听、数据统计、位置信息获取、地图创建与标记等步骤。同时,分析了关键技术点,讨论了可能遇到的问题及解决方案,并提出了扩展与优化建议。通过这个案例,我们可以更好地理解大数据的存储、处理和可视化技术,为处理其他类似的大数据问题提供参考。
以下是整个流程的另一个mermaid流程图,展示了从数据获取到可视化的完整过程:
graph LR
A[获取认证信息] --> B[加载参议员数据]
B --> C[连接MongoDB]
C --> D[启动推特流监听]
D --> E[存储推特数据]
E --> F[统计推特数量]
F --> G[获取各州位置信息]
G --> H[按州分组数据]
H --> I[创建地图]
I --> J[创建热力图]
J --> K[创建地图标记]
K --> L[保存地图]
通过以上的步骤和分析,我们可以完成一个完整的大数据案例,从数据的获取、存储到最终的可视化展示,为数据分析和决策提供有力支持。
超级会员免费看

被折叠的 条评论
为什么被折叠?



