2、数据源获取:公告数据来源与爬虫基础

做事件驱动策略,第一步就是搞定数据。没有数据,再牛的策略也是空中楼阁。

我个人习惯把公告数据源分成三类:官方渠道、商业终端、财经门户。这三类各有优劣,咱们一个一个说。

2.1 三大数据源对比

先看一张表,你心里就有数了:

数据源 覆盖范围 更新速度 获取成本 适合场景
巨潮资讯网 沪深京A股全量公告 实时(交易所直连) 免费 个人研究、小规模策略
东方财富 A股+港股+基金 延迟5-15分钟 免费/付费API 快速原型、回测验证
Wind 全市场+历史数据 实时 昂贵(年费数万) 机构级、高频交易

巨潮资讯网是证监会指定的信息披露网站。说白了,所有上市公司必须在这里发公告。这是最权威的源头,而且免费。我刚开始做策略时,就是靠爬巨潮的数据起家的。

东方财富的数据其实是从巨潮拿的,但它做了二次加工。比如把PDF转成文本、提取关键字段。这对我们做文本分析很有帮助。不过要注意,它偶尔会漏公告或者格式出错。

Wind是机构标配。数据全、接口稳定、售后好。但价格嘛...嗯,个人用户基本不用考虑。我在私募工作时用过Wind的API,确实方便,但每年十几万的费用不是小数目。

2.2 API接口调用实战

我个人最推荐的方式是直接调API。为什么?稳定、高效、不用跟反爬斗智斗勇。

以东方财富的开放平台为例,获取公告列表的代码很简单:

import requests
import json

# 东方财富公告API示例
url = "https://push2.eastmoney.com/api/qt/stock/get"
params = {
    "secid": "1.600519",  # 贵州茅台
    "fields": "f57,f58,f170"
}
headers = {
    "User-Agent": "Mozilla/5.0"
}

resp = requests.get(url, params=params, headers=headers)
data = resp.json()
print(data)

你看,几行代码就能拿到实时数据。但这里有个坑——API的调用频率限制。我曾经在回测时没注意限流,直接发了上千个请求,结果IP被封了24小时。嗯,从那以后我都在代码里加上了sleep。

小技巧:调用API时,建议每次请求间隔至少0.5秒。如果数据量大,可以用异步请求+队列的方式,既保证速度又不触发限流。

2.3 数据爬虫基础

如果API满足不了你,或者你想爬巨潮这种没有开放接口的网站,那就得用爬虫了。

爬公告数据,核心就三步:

  1. 找到公告列表页——通常是按日期分页的HTML页面
  2. 解析公告链接——提取每个公告的详情页URL
  3. 下载公告内容——一般是PDF或HTML格式

举个例子,爬巨潮的公告列表:

import requests
from bs4 import BeautifulSoup

base_url = "http://www.cninfo.com.cn/new/disclosure"
params = {
    "stockCode": "600519",
    "pageNum": 1,
    "pageSize": 30
}

resp = requests.get(base_url, params=params)
soup = BeautifulSoup(resp.text, 'html.parser')

# 找到所有公告条目
items = soup.select('.announcement-item')
for item in items:
    title = item.select_one('.title').text.strip()
    link = item.select_one('a')['href']
    date = item.select_one('.date').text.strip()
    print(f"{date} - {title}")

这里要注意,巨潮的页面结构偶尔会改。我去年就遇到过,某天突然发现爬虫全挂了,排查了半天才发现是CSS类名变了。所以建议你定期检查爬虫是否正常工作。

避坑指南:我曾经因为爬虫频率太高,被巨潮的WAF(Web应用防火墙)拦截了。后来加了随机User-Agent和代理IP池才解决。记住:爬虫不是越快越好,稳定才是王道。

2.4 数据存储与清洗

数据拿到手,不能直接扔进策略里。公告数据通常很脏,需要清洗。

常见的坑:

  • PDF乱码——有些公告是扫描件,OCR识别率低
  • 重复公告——同一份公告可能在多个平台出现
  • 格式不统一——有的用"万元",有的用"元"

我的做法是:先存成JSON格式,保留原始字段。然后写一个清洗函数,统一处理数值单位、去除空白字符、去重。最后再入库。

# 数据清洗示例
def clean_announcement(data):
    # 去除前后空格
    data['title'] = data['title'].strip()
    # 统一日期格式
    data['date'] = data['date'].replace('年', '-').replace('月', '-').replace('日', '')
    # 数值单位转换
    if '万元' in data['amount']:
        data['amount'] = float(data['amount'].replace('万元', '')) * 10000
    return data

核心要点:数据源的选择取决于你的预算和需求。个人做策略,巨潮+东方财富完全够用。机构用户可以考虑Wind。爬虫是最后的手段,能用API就别爬。

好了,数据源这块就聊到这儿。你想想看,其实核心就三个问题:数据从哪来、怎么拿、怎么存。搞定了这些,后面的策略分析才有基础。


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