Python爬虫实战:5分钟搞定东方财富网股票数据抓取(附完整代码)
最近在研究量化交易的朋友们可能深有体会——获取高质量的股票数据是第一步,也是最让人头疼的一步。市面上虽然有各种数据接口,但要么收费昂贵,要么数据不全。今天我要分享一个实战技巧:如何用Python快速抓取东方财富网的股票数据,整个过程不到5分钟,而且代码简单到连Python初学者都能轻松上手。
1. 准备工作与环境配置
在开始之前,确保你的电脑已经安装了Python环境(建议3.7以上版本)。我们需要用到几个关键的Python库:
pip install requests pandas- requests:用于发送HTTP请求获取网页数据
- pandas:用于数据处理和Excel文件导出
如果你打算长期使用这个爬虫,建议配置一个虚拟环境:
python -m venv stock_env source stock_env/bin/activate # Linux/Mac stock_env\Scripts\activate # Windows2. 分析东方财富网的数据接口
东方财富网的股票数据实际上是通过API接口提供的,这比直接解析HTML要方便得多。通过浏览器开发者工具(F12),我们可以找到数据接口的URL模式:
https://7.push2.eastmoney.com/api/qt/clist/get?cb=jQuery...&pn=1&pz=20&...&fid=f3&fs=m:0+t:6...这个URL有几个关键参数:
| 参数 | 说明 | 示例值 |
|---|---|---|
| pn | 页码 | 1 |
| pz | 每页数据量 | 20 |
| fid | 数据字段标识 | f3 |
| fs | 市场板块代码 | m:0+t:6 |
3. 核心爬虫代码实现
下面是完整的爬虫代码,我已经做了详细注释:
import requests import re import pandas as pd # 设置请求头,模拟浏览器访问 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Referer": "https://quote.eastmoney.com/" } def clean_api_response(text): """清理API返回的JSONP格式数据""" # 移除JSONP回调函数包裹 text = re.sub(r'^.*?(?=\()', '', text, count=1) text = re.sub(r'\);$', '', text) return text def fetch_stock_data(market_code, page=1): """获取指定市场和页面的股票数据""" url = f"https://7.push2.eastmoney.com/api/qt/clist/get" params = { "pn": page, "pz": 20, "fid": "f3", "fs": market_code, "fields": "f12,f14,f2,f3,f4,f5,f6,f7,f8,f9,f10,f15,f16,f17,f18,f23" } response = requests.get(url, headers=headers, params=params) cleaned_data = clean_api_response(response.text) return eval(cleaned_data) def get_all_stocks(market_name, market_code): """获取指定市场的所有股票数据""" all_stocks = [] page = 1 while True: print(f"正在获取 {market_name} 第 {page} 页数据...") data = fetch_stock_data(market_code, page) if not data.get('data') or not data['data'].get('diff'): break for item in data['data']['diff']: stock = { "代码": item.get("f12", ""), "名称": item.get("f14", ""), "最新价": item.get("f2", 0), "涨跌幅": item.get("f3", 0), "成交量(手)": item.get("f5", 0), "成交额": item.get("f6", 0), "市盈率": item.get("f9", 0) } all_stocks.append(stock) page += 1 return pd.DataFrame(all_stocks) # 定义不同市场的代码 MARKETS = { "沪深A股": "m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23", "创业板": "m:0+t:80", "科创板": "m:1+t:23" } # 获取并保存所有市场数据 for name, code in MARKETS.items(): df = get_all_stocks(name, code) df.to_excel(f"{name}_股票数据.xlsx", index=False) print(f"{name}数据已保存,共{len(df)}条记录")4. 代码优化与实用技巧
在实际使用中,你可能需要做一些优化:
- 请求间隔:添加适当的延时,避免被封IP
import time time.sleep(1) # 每次请求间隔1秒- 错误处理:增加重试机制
from retrying import retry @retry(stop_max_attempt_number=3, wait_fixed=2000) def fetch_stock_data(market_code, page=1): try: # 原有代码... except Exception as e: print(f"请求失败: {e}") raise- 数据更新:只获取最新数据
# 先读取已有的Excel文件 try: old_df = pd.read_excel("沪深A股_股票数据.xlsx") old_codes = set(old_df["代码"]) except FileNotFoundError: old_codes = set() # 只保留新股票 new_stocks = [s for s in all_stocks if s["代码"] not in old_codes]提示:东方财富网的API有一定频率限制,建议控制请求速度,避免短时间内发送过多请求。
5. 数据应用场景示例
获取到的股票数据可以用于多种分析:
- 基本面分析:利用市盈率、市净率等指标筛选股票
- 技术分析:计算各种技术指标
- 量化策略:作为量化交易的基础数据
这里展示一个简单的市盈率筛选示例:
# 读取数据 df = pd.read_excel("沪深A股_股票数据.xlsx") # 筛选市盈率在0-30之间的股票 good_pe = df[(df["市盈率"] > 0) & (df["市盈率"] < 30)] # 按市盈率排序 good_pe = good_pe.sort_values("市盈率") print(f"找到{len(good_pe)}只低估值股票:") print(good_pe[["代码", "名称", "市盈率"]].head(10))6. 常见问题与解决方案
在实际使用中,你可能会遇到以下问题:
返回数据为空
- 检查market_code是否正确
- 尝试更换User-Agent
- 检查IP是否被封
数据字段不匹配
- 确认fields参数包含所需字段
- 参考东方财富网页面显示的数据
数据量太大
- 增加每页数据量(pz参数)
- 分市场、分时间段获取
数据更新不及时
- 东方财富网的数据通常有15分钟延迟
- 对于实时性要求高的场景,考虑其他数据源
7. 进阶扩展思路
如果你想进一步扩展这个爬虫,可以考虑:
- 添加定时任务,每天自动更新数据
- 将数据存入数据库而非Excel
- 增加更多数据字段和分析功能
- 开发可视化界面展示数据
# 示例:使用APScheduler设置定时任务 from apscheduler.schedulers.blocking import BlockingScheduler def job(): print("开始定时获取股票数据...") # 调用之前的获取数据代码 scheduler = BlockingScheduler() scheduler.add_job(job, 'cron', hour=15, minute=30) # 每天15:30运行 scheduler.start()这个爬虫虽然简单,但已经能够满足大多数个人投资者的数据需求。我在自己的量化交易系统中就使用了类似的代码,运行半年多来一直很稳定。对于初学者来说,这个项目也是个很好的练手机会,你可以尝试添加更多功能,比如自动邮件发送数据报告、异常监控等。