2. 基于社交媒体帖子的情绪分析

任务目标

从Reddit的WallStreetBets子版块抓取提及指定股票代码(如GME)的帖子标题,使用基于词典的文本情感分析方法判断每条帖子的看涨/看跌情绪,并统计整体情绪分布比例。

实现方案

使用praw库访问Reddit公开API(无需的只读模式),抓取最近100条提及目标股票代码的帖子标题。情感分析采用金融领域专用词典FinBERT的简化替代方案——基于TextBlob的主观性+极性双阈值判断:极性大于0.1且主观性大于0.3标记为看涨,极性小于-0.1且主观性大于0.3标记为看跌,其余为中性。该方法无需下载大模型,可在本地快速运行。

环境依赖

pip install praw textblob
python -m textblob.download_corpora

完整代码

import praw
from textblob import TextBlob
from collections import Counter

# ========== 配置区 ==========
STOCK_TICKER = "GME"        # 目标股票代码
POST_LIMIT = 100            # 抓取帖子数量
SUBREDDIT_NAME = "wallstreetbets"

# Reddit只读访问(无需创建应用,使用公共凭证)
reddit = praw.Reddit(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
    user_agent="sentiment_analysis_script/1.0"
)

# ========== 抓取帖子 ==========
subreddit = reddit.subreddit(SUBREDDIT_NAME)
posts = []
for submission in subreddit.search(STOCK_TICKER, limit=POST_LIMIT):
    posts.append(submission.title)

print(f"抓取到 {len(posts)} 条提及 {STOCK_TICKER} 的帖子")

# ========== 情感分析 ==========
def classify_sentiment(text):
    """基于TextBlob的金融情绪分类"""
    blob = TextBlob(text)
    polarity = blob.sentiment.polarity      # 范围[-1,1]
    subjectivity = blob.sentiment.subjectivity  # 范围[0,1]
    
    if polarity > 0.1 and subjectivity > 0.3:
        return "看涨"
    elif polarity < -0.1 and subjectivity > 0.3:
        return "看跌"
    else:
        return "中性"

results = []
for title in posts:
    sentiment = classify_sentiment(title)
    results.append({"text": title, "sentiment": sentiment})

# ========== 统计与输出 ==========
sentiment_counts = Counter(r["sentiment"] for r in results)
total = len(results)

print(f"\n===== {STOCK_TICKER} 情绪分析结果 =====")
print(f"总帖子数: {total}")
for sentiment in ["看涨", "看跌", "中性"]:
    count = sentiment_counts.get(sentiment, 0)
    percentage = (count / total * 100) if total > 0 else 0
    print(f"{sentiment}: {count} 条 ({percentage:.1f}%)")

print("\n===== 样本展示(前5条) =====")
for r in results[:5]:
    print(f"[{r['sentiment']}] {r['text'][:80]}")

运行方式

  1. 在Reddit开发者平台创建一个"script"类型应用,获取client_id和client_secret(只读访问不需要配置redirect_uri)
  2. 将代码中的YOUR_CLIENT_ID和YOUR_CLIENT_SECRET替换为实际值
  3. 运行脚本:python sentiment_analysis.py

验证方法

脚本执行后应输出:抓取帖子数量(通常为100条,若该股票讨论不足则少于100)、三类情绪各自的数量与百分比、以及前5条帖子的分类示例。通过以下标准判断运行成功:

  • 输出无异常报错,且"总帖子数"大于0
  • 三类情绪百分比之和为100%
  • 随机抽取2-3条被分类为"看涨"或"看跌"的帖子标题人工阅读,确认分类结果与标题语义基本一致(例如包含"moon""rocket"等词倾向看涨,包含"dump""crash"等词倾向看跌)

注意事项

Reddit的搜索功能返回的是相关性排序而非时间排序,因此结果可能包含旧帖子。若需按时间抓取,可将subreddit.search()替换为subreddit.new(limit=POST_LIMIT)并自行过滤标题中包含股票代码的帖子。TextBlob词典对金融俚语(如"diamond hands""tendies")识别有限,实际使用中可扩展自定义词典提升准确率。