1. 股票数据爬虫实战概述
金融数据爬取与分析是Python技术栈的经典应用场景。不同于常规的静态网页爬虫,股票数据爬取具有三个显著特点:数据实时更新、接口标准化程度高、对后续处理要求严格。本文将完整演示从数据获取到专业分析的全流程,使用Python生态中最轻量且高效的库组合。
提示:所有操作请严格遵守相关法律法规,本文代码仅用于技术学习目的。
2. 核心工具链选型解析
2.1 爬虫组件选择
我们采用requests+BeautifulSoup的基础组合,而非Scrapy等重型框架,原因有三:
- 股票数据接口多为RESTful API,不需要复杂的页面解析
- 轻量级组合更易于调试和定制化
- 运行效率更高,适合高频请求场景
python复制import requests
from bs4 import BeautifulSoup
import pandas as pd
2.2 可视化方案对比
经过实测对比多个库后,选择mplfinance的原因:
- 原生支持金融数据可视化
- 内置蜡烛图、成交量等专业图表类型
- 与Matplotlib生态无缝集成
- API设计符合金融从业者习惯
3. 实战爬取流程详解
3.1 接口分析与逆向工程
以东方财富网接口为例,通过浏览器开发者工具分析请求:
- 打开股票详情页(如600519)
- 按F12进入Network面板
- 筛选XHR请求,观察数据接口
典型股票接口特征:
- 请求方式:GET
- 返回格式:JSON
- 关键参数:股票代码、周期类型
3.2 请求头关键配置
金融接口通常有基础反爬措施,必须配置:
python复制headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Referer': 'https://finance.sina.com.cn/'
}
3.3 数据获取完整代码
python复制def get_stock_data(code, period='daily'):
url = f'https://finance.sina.com.cn/realstock/company/{code}/{period}.js'
try:
resp = requests.get(url, headers=headers)
data = resp.json()
return pd.DataFrame(data['data'])
except Exception as e:
print(f"获取数据失败: {str(e)}")
return None
4. 数据清洗关键步骤
4.1 字段标准化处理
原始数据需要转换为标准OHLCV格式:
| 原始字段 | 标准字段 | 转换说明 |
|---|---|---|
| day | date | 转为datetime |
| open | open | 保持不变 |
| high | high | 保持不变 |
| low | low | 保持不变 |
| close | close | 保持不变 |
| volume | volume | 转为整数 |
4.2 异常数据处理
常见问题及解决方案:
-
缺失值处理:
- 前向填充:
df.fillna(method='ffill') - 线性插值:
df.interpolate()
- 前向填充:
-
异常值检测:
python复制# 识别3个标准差外的异常值 mean = df['close'].mean() std = df['close'].std() df[(df['close'] > mean + 3*std) | (df['close'] < mean - 3*std)]
5. 专业K线图绘制
5.1 基础K线实现
python复制import mplfinance as mpf
# 确保列名正确
df = df.rename(columns={
'day': 'Date',
'open': 'Open',
'high': 'High',
'low': 'Low',
'close': 'Close',
'volume': 'Volume'
})
# 设置日期索引
df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)
# 绘制基础K线
mpf.plot(df, type='candle', style='charles')
5.2 高级图表配置
添加移动平均线和成交量:
python复制kwargs = dict(
type='candle',
mav=(5, 10, 20),
volume=True,
style='binance',
title='贵州茅台(600519) K线图',
ylabel='价格',
ylabel_lower='成交量'
)
mpf.plot(df, **kwargs)
6. 量化分析实战
6.1 技术指标计算
移动平均线计算:
python复制df['MA5'] = df['Close'].rolling(5).mean()
df['MA10'] = df['Close'].rolling(10).mean()
MACD指标实现:
python复制# 计算短期EMA
df['EMA12'] = df['Close'].ewm(span=12, adjust=False).mean()
# 计算长期EMA
df['EMA26'] = df['Close'].ewm(span=26, adjust=False).mean()
# 计算DIF
df['DIF'] = df['EMA12'] - df['EMA26']
# 计算DEA
df['DEA'] = df['DIF'].ewm(span=9, adjust=False).mean()
# 计算MACD柱
df['MACD'] = (df['DIF'] - df['DEA']) * 2
6.2 交易信号生成
基于均线交叉策略:
python复制df['Signal'] = 0
df.loc[df['MA5'] > df['MA10'], 'Signal'] = 1 # 买入信号
df.loc[df['MA5'] < df['MA10'], 'Signal'] = -1 # 卖出信号
7. 常见问题解决方案
7.1 数据获取问题
问题1:返回403错误
- 原因:缺失必要请求头
- 解决:确保包含User-Agent和Referer
问题2:数据为空
- 检查股票代码格式:
- 沪市:sh600519
- 深市:sz000001
7.2 可视化问题
问题1:KeyError异常
- 确保列名完全匹配:
- Open, High, Low, Close, Volume
问题2:日期显示异常
- 必须完成两步:
python复制df['Date'] = pd.to_datetime(df['Date']) df.set_index('Date', inplace=True)
8. 性能优化技巧
8.1 请求优化
-
使用会话保持:
python复制
session = requests.Session() session.headers.update(headers) -
设置合理超时:
python复制requests.get(url, timeout=(3.05, 5))
8.2 数据处理加速
-
使用向量化操作:
python复制# 慢:循环计算 for i in range(len(df)): df.loc[i, 'pct_change'] = (df.loc[i, 'close'] - df.loc[i-1, 'close'])/df.loc[i-1, 'close'] # 快:向量化计算 df['pct_change'] = df['close'].pct_change() -
使用category类型:
python复制df['code'] = df['code'].astype('category')
9. 完整代码架构
python复制# config.py
HEADERS = {...}
API_URL = '...'
# data_fetcher.py
class StockDataFetcher:
def __init__(self):
self.session = requests.Session()
def fetch(self, code, period):
...
# data_processor.py
class DataProcessor:
@staticmethod
def clean_data(raw_df):
...
@staticmethod
def add_technical_indicators(df):
...
# visualizer.py
class StockVisualizer:
@staticmethod
def plot_kline(df, **kwargs):
...
# main.py
def main():
fetcher = StockDataFetcher()
processor = DataProcessor()
visualizer = StockVisualizer()
raw_data = fetcher.fetch('sh600519', 'daily')
clean_data = processor.clean_data(raw_data)
final_data = processor.add_technical_indicators(clean_data)
visualizer.plot_kline(final_data)
10. 扩展应用方向
-
多股票对比分析:
- 同时获取多只股票数据
- 计算相对强弱指数(RSI)
-
量化回测系统:
python复制from backtrader import Cerebro cerebro = Cerebro() data = PandasData(dataname=df) cerebro.adddata(data) -
实时监控预警:
- 设置价格提醒
- 异常波动检测
重要提示:在实际应用中,请特别注意数据更新频率和接口调用限制,避免对目标服务器造成过大压力。建议添加适当的延时和错误重试机制。