数据采集基础:用Python搞定金融与社交媒体数据
各位同学,今天我们来聊聊数据采集。说实话,这个环节是整个模型的地基。地基没打好,后面再漂亮的算法也是空中楼阁。我自己在项目里踩过不少坑,今天把这些经验都掏出来给你们。
核心要点:金融数据 + 社交媒体数据 → 清洗对齐 → 可用数据集
2.1 金融数据获取:yfinance库实战
yfinance这个库,我用它抓过美股、港股、A股的数据。说白了,它就是雅虎财经的Python封装,简单到令人发指。
安装就一行命令:
pip install yfinance
我习惯这样写获取代码:
import yfinance as yf
import pandas as pd
# 获取某只股票的历史数据
ticker = "AAPL"
start_date = "2024-01-01"
end_date = "2024-12-31"
data = yf.download(ticker, start=start_date, end=end_date)
print(data.head())
你想想看,就这么几行代码,开盘价、收盘价、最高价、最低价、成交量全都有了。嗯,这里要注意——yfinance返回的是DataFrame,索引是日期,列名是英文。
我的小技巧:我一般会加个参数 auto_adjust=True,这样拿到的价格是复权后的,省得自己手动调整分红拆股。
获取多只股票也很简单:
tickers = ["AAPL", "MSFT", "GOOGL"]
data = yf.download(tickers, start="2024-01-01", end="2024-12-31")
# 返回的是MultiIndex DataFrame,列名是 (Price_Type, Ticker)
为什么会这样?因为雅虎财经把不同股票的数据堆在一起了。我个人习惯用 .xs() 方法提取某只股票的数据:
aapl_close = data.xs("AAPL", level=1, axis=1)["Close"]
2.2 社交媒体数据获取:Tweepy与微博API
金融数据只是半边天。市场情绪从哪来?社交媒体啊!
我曾经做过一个项目,发现推特上的负面情绪比财报数据提前两天反映股价波动。所以这块数据,必须拿下。
2.2.1 Tweepy 获取推特数据
先装库:
pip install tweepy
然后你需要去Twitter Developer Portal申请API密钥。这个流程有点烦,但没办法。
import tweepy
# 配置API密钥
bearer_token = "你的Bearer Token"
client = tweepy.Client(bearer_token=bearer_token)
# 搜索最近7天的推文
query = "AAPL stock"
tweets = client.search_recent_tweets(query=query, max_results=100)
for tweet in tweets.data:
print(tweet.text)
避坑指南:我曾经因为没处理API限流,程序跑一半就挂了。免费版每15分钟只能请求450次。建议加个time.sleep(),或者用tweepy自带的等待机制。
2.2.2 微博API获取数据
微博API的申请门槛比推特高一些。不过如果你有企业认证,流程会顺畅很多。
import requests
import json
# 微博API配置
app_key = "你的App Key"
app_secret = "你的App Secret"
access_token = "你的Access Token"
# 搜索微博内容
url = "https://api.weibo.com/2/statuses/public_timeline.json"
params = {
"access_token": access_token,
"count": 50
}
response = requests.get(url, params=params)
data = response.json()
for status in data["statuses"]:
print(status["text"])
说实话,微博API返回的数据结构比推特复杂。我建议先打印出来看看字段结构,再决定提取哪些信息。
2.3 数据清洗与对齐
数据拿到手了,但问题来了——金融数据是每天一条,社交媒体数据是每分钟几十条。怎么对齐?
我一般分三步走:
- 清洗金融数据:处理缺失值、去除停牌日
- 清洗社交媒体数据:去重、过滤垃圾内容、情感打分
- 时间对齐:按日聚合社交媒体数据,与金融数据匹配
2.3.1 金融数据清洗
# 处理缺失值
data = data.dropna() # 或者用 data.fillna(method='ffill')
# 只保留交易日
data = data[data['Volume'] > 0]
2.3.2 社交媒体数据清洗
import re
from datetime import datetime
def clean_tweet(text):
# 去除URL
text = re.sub(r'http\S+', '', text)
# 去除@提及
text = re.sub(r'@\w+', '', text)
# 去除特殊字符
text = re.sub(r'[^\w\s]', '', text)
return text.strip()
# 假设tweets_df是包含推文数据的DataFrame
tweets_df['clean_text'] = tweets_df['text'].apply(clean_tweet)
# 过滤掉空文本
tweets_df = tweets_df[tweets_df['clean_text'] != '']
2.3.3 时间对齐
这是最关键的步骤。我习惯把社交媒体数据按天聚合,计算每日情感得分:
# 假设tweets_df有created_at列
tweets_df['date'] = pd.to_datetime(tweets_df['created_at']).dt.date
# 按天计算情感得分(这里用简单的正面/负面词计数)
def sentiment_score(text):
positive_words = ['up', 'gain', 'profit', 'bullish', 'buy']
negative_words = ['down', 'loss', 'bearish', 'sell', 'crash']
score = 0
for word in positive_words:
if word in text.lower():
score += 1
for word in negative_words:
if word in text.lower():
score -= 1
return score
tweets_df['sentiment'] = tweets_df['clean_text'].apply(sentiment_score)
# 按天聚合
daily_sentiment = tweets_df.groupby('date')['sentiment'].mean().reset_index()
daily_sentiment.columns = ['date', 'avg_sentiment']
# 与金融数据合并
financial_data = yf.download("AAPL", start="2024-01-01", end="2024-12-31")
financial_data['date'] = financial_data.index.date
merged_data = pd.merge(financial_data, daily_sentiment, on='date', how='left')
# 没有社交媒体数据的日期,用前一天的填充
merged_data['avg_sentiment'] = merged_data['avg_sentiment'].fillna(method='ffill')
我的经验:对齐的时候,一定要检查日期范围是否匹配。我曾经因为时区问题,导致金融数据和社交媒体数据错位了一天。建议统一用UTC时间。
2.4 本章知识体系
下面这张图,是我自己梳理的数据采集流程。你看一眼,心里就有谱了。
这张图把整个流程串起来了。从左到右,从上到下,每一步都有对应的代码实现。你跟着走一遍,基本不会出大问题。
最后提醒一句:API密钥千万别提交到GitHub。我见过太多人因为这个被扣费。建议用环境变量或者配置文件管理密钥。
好了,数据采集这块就讲到这里。代码都给了,流程也画了,剩下的就是你自己动手跑一遍。记住,数据质量决定模型上限,别在这个环节偷懒。