3、数据采集与清洗:社交媒体API调用(Twitter/微博),新闻爬虫基础,数据清洗与预处理(去噪、标准化)

做情绪数据与价格联动模型,第一步不是建模,而是搞数据。

我见过太多人一上来就调包跑LSTM,结果数据里全是垃圾,模型自然一塌糊涂。说白了,情绪数据这东西,比K线数据脏得多。K线好歹是交易所出来的标准化数据,情绪数据呢?推特上的表情包、微博里的阴阳怪气、新闻标题的夸张修辞……全是噪音。

这一章,我们就来解决这个问题。我会把我在实战中踩过的坑、总结的经验,一股脑倒出来。

3.1 社交媒体API调用:Twitter与微博

先聊Twitter。Twitter的API v2是目前的主流。我个人习惯用 tweepy 这个库,封装得比较舒服。

你需要先去Twitter Developer Portal申请一个Bearer Token。嗯,这里要注意,免费版有速率限制,每分钟只能拉450条。做量化研究其实够用了,但如果你要实盘高频扫描,得升级到Academic Research级别。

核心思路: 用关键词+时间窗口去捞推文,然后提取文本、时间戳、互动量(like/retweet)。
import tweepy
import pandas as pd

# 初始化客户端
client = tweepy.Client(bearer_token='你的Bearer Token')

# 搜索关键词
query = '比特币 OR BTC OR 加密货币 lang:en -is:retweet'
tweets = client.search_recent_tweets(
    query=query,
    max_results=100,
    tweet_fields=['created_at', 'public_metrics']
)

# 提取数据
data = []
for tweet in tweets.data:
    data.append({
        'text': tweet.text,
        'time': tweet.created_at,
        'likes': tweet.public_metrics['like_count'],
        'retweets': tweet.public_metrics['retweet_count']
    })

df = pd.DataFrame(data)
print(df.head())

微博呢?说实话,微博的API比Twitter难搞。官方API对个人开发者限制很多,而且中文文本的处理比英文复杂——分词、表情符号、@用户、话题标签……全是坑。

我曾经试过用 weibo-scraper 这类第三方工具,但稳定性堪忧。后来我改用Selenium模拟浏览器抓取,虽然慢,但胜在可控。不过要注意,微博的反爬机制挺严的,频繁请求会被封IP。

我的建议: 如果只是做研究,优先用Twitter数据。微博数据可以买第三方清洗好的数据源,省时省力。

3.2 新闻爬虫基础

新闻数据和社交媒体数据,性质完全不同。社交媒体是「情绪的快照」,新闻是「事件的记录」。做联动模型时,两者都要用。

新闻爬虫,我推荐 newspaper3k 这个库。它能把一篇新闻的标题、正文、发布时间、作者、摘要全扒下来,而且自带一些去噪功能。

from newspaper import Article

url = 'https://www.coindesk.com/...'
article = Article(url)
article.download()
article.parse()

news_data = {
    'title': article.title,
    'text': article.text,
    'publish_date': article.publish_date,
    'summary': article.summary
}

但这里有个坑:新闻网站的HTML结构经常变。你想想看,今天爬得好好的,明天网站改版了,你的解析逻辑就全废了。所以我一般会加一层异常处理,爬不到就跳过,别让一个坏链接卡死整个流程。

注意: 新闻爬虫要遵守robots.txt。别为了数据把人家服务器搞崩了。我一般设置每次请求间隔2-3秒,并且用代理池轮换IP。

3.3 数据清洗与预处理:去噪、标准化

数据拿到手了,但离能用还差得远。社交媒体和新闻文本里,充斥着大量噪音。

3.3.1 去噪

去噪,说白了就是把没用的东西扔掉。我总结了一套标准流程:

  1. 去除HTML标签:新闻正文里偶尔会残留 <p><br> 之类的标签。
  2. 去除URL和@提及:推特里的链接和@用户,对情绪分析没意义。
  3. 去除特殊符号和emoji:除非你要分析emoji情绪,否则建议去掉。但注意,有些emoji有明确情绪倾向(比如😡、😂),如果你要做细粒度分析,可以保留并映射成文字。
  4. 去除停用词:中文的「的、了、是」,英文的「the、a、is」——这些词不承载情绪。
  5. 去除重复内容:同一个新闻被多家媒体转载,内容几乎一样。我一般用SimHash去重。
import re
import emoji

def clean_text(text):
    # 去HTML标签
    text = re.sub(r'<[^>]+>', '', text)
    # 去URL
    text = re.sub(r'http\S+', '', text)
    # 去@提及
    text = re.sub(r'@\w+', '', text)
    # 去emoji(可选)
    text = emoji.replace_emoji(text, replace='')
    # 去多余空格
    text = re.sub(r'\s+', ' ', text).strip()
    return text

3.3.2 标准化

标准化,就是把不同来源的数据拉到同一个尺度上。比如Twitter的互动量是几百,新闻的阅读量可能是几万,直接放一起建模会出问题。

我常用的标准化方法有两种:

方法 公式 适用场景
Z-score标准化 (x - μ) / σ 数据近似正态分布时
Min-Max标准化 (x - min) / (max - min) 数据有明确上下界时

我个人习惯用Z-score。为什么?因为情绪数据经常有极端值——比如一条推文突然爆火,互动量是平时的100倍。Min-Max会被这种极端值压扁,而Z-score还能保留相对关系。

避坑指南: 标准化一定要在训练集上计算参数,然后应用到测试集。千万别把整个数据集一起标准化——那叫数据泄露,模型在实盘时会崩得很惨。

3.4 知识体系总览

下面这张图,是我自己梳理的数据采集与清洗流程。你可以把它当作一个检查清单。

情绪数据采集与清洗流程 社交媒体 Twitter / 微博 新闻媒体 CoinDesk / 财新 其他来源 论坛 / 聊天群 API调用 tweepy / 微博SDK 网页爬虫 newspaper3k / Scrapy 第三方数据 清洗好的数据源 数据去噪 去HTML标签 → 去URL → 去@提及 → 去emoji → 去停用词 → 去重 数据标准化 Z-score 或 Min-Max → 统一尺度 → 避免数据泄露 图:情绪数据从采集到可用的完整链路

你看,从数据源到最终可用的标准化数据,中间要经过好几道工序。每一道工序都可能出问题——API限流、爬虫被封、去噪过度把情绪词也删了……

我刚开始做这个模型时,花在数据清洗上的时间,比建模多三倍。但后来发现,这时间花得值。数据干净了,模型自然就听话了。

一个小技巧: 每次清洗完数据,都保存一份原始副本。万一清洗逻辑有bug,你还能回溯。我吃过这个亏——有一次去重逻辑写错了,把关键数据全删了,还好有备份。

好了,数据采集和清洗就聊到这儿。下一章我们会把这些清洗好的情绪数据,和价格数据对齐,然后开始做特征工程。嗯,那才是真正有意思的部分。


公众号:蓝海资料掘金营,微信deep3321