)
1. 为什么需要东方财富网股票数据爬虫做量化交易或者数据分析的朋友都知道获取高质量的股票数据是第一步。东方财富网作为国内领先的金融数据平台提供了丰富的股票行情数据但手动复制粘贴显然不现实。这时候就需要一个自动化爬虫来帮我们搞定这件事。我去年刚开始做量化的时候就遇到过数据获取的难题。当时试了好几个数据源要么收费太贵要么数据不全。后来发现东方财富网的接口数据质量不错而且是免费的就决定自己写个爬虫。没想到这一写就是好几个通宵踩了不少坑才搞定。2. 准备工作与环境搭建2.1 必备工具和库要开发这个爬虫我们需要准备以下工具Python 3.7建议用最新稳定版requests库发送HTTP请求pandas库数据处理re库正则表达式处理安装这些库很简单用pip一行命令就能搞定pip install requests pandas2.2 分析目标网站结构东方财富网的股票数据页面看起来是个典型的动态网页。打开开发者工具F12切换到Network标签然后刷新页面。你会发现真正的数据是通过XHR请求获取的而不是直接写在HTML里。关键点来了我们需要找到那个返回股票数据的API接口。经过一番查找我发现这个接口https://7.push2.eastmoney.com/api/qt/clist/get这个接口返回的是JSONP格式的数据需要特殊处理才能使用。3. 核心爬虫代码实现3.1 处理JSONP数据东方财富网的接口返回的是JSONP格式这意味着数据被包裹在一个函数调用里。我们需要用正则表达式把这个外壳去掉import re def parse_jsonp(jsonp_str): # 找到开头到第一个(的部分 left_data re.search(r^.*?(?\(), jsonp_str).group() # 将匹配到的内容加上(替换成空字符串 data re.sub(left_data \(, , jsonp_str) # 将结尾的);替换成空字符串 data re.sub(\);, , data) return data这里有个坑要注意直接匹配jQuery112400...(这样的字符串可能会出错因为括号在正则里有特殊含义。我的做法是先匹配到(之前的部分再拼接上转义后的括号进行替换。3.2 构建请求参数东方财富网的接口有几个关键参数pn页码pz每页数据量fid字段IDfs筛选条件我整理了一个板块映射字典方便切换不同市场板块market_map { 沪深京A股: f3fsm:0t:6,m:0t:80,m:1t:2,m:1t:23,m:0t:81s:2048, 上证A股: f3fsm:1t:2,m:1t:23, 创业板: f3fsm:0t:80, # 其他板块... }3.3 分页爬取逻辑爬取数据时要处理分页问题。我发现当请求的页码超出范围时接口会返回data:null。利用这个特点可以设置停止条件null null # 需要定义这个变量否则eval会报错 def crawl_market(market_name, market_code): page 1 all_data [] while True: url fhttps://7.push2.eastmoney.com/api/qt/clist/get?...pn{page}pz20fid{market_code} response requests.get(url) data eval(parse_jsonp(response.text)) if data[data] null: break # 处理数据... page 1 return all_data4. 数据解析与存储4.1 字段映射关系东方财富网返回的数据字段都是用f1,f2这样的缩写表示的。经过分析我整理出了这些字段对应的实际含义字段含义字段含义f2最新价f12股票代码f3涨跌幅f14股票名称f4涨跌额f15最高价............4.2 数据清洗与转换原始数据中有一些需要特别注意的地方价格字段可能是整数或浮点数涨跌幅是百分比需要除以100有些字段可能为空需要处理def clean_data(raw_data): cleaned { 代码: raw_data[f12], 名称: raw_data[f14], 最新价: float(raw_data[f2]), 涨跌幅: float(raw_data[f3]) / 100, # 其他字段... } return cleaned4.3 存储到Excel使用pandas可以很方便地把数据保存为Excelimport pandas as pd def save_to_excel(data, filename): df pd.DataFrame(data) df.to_excel(filename, indexFalse)5. 反爬策略与优化5.1 请求头设置东方财富网对请求头有一些基本检查至少要设置User-Agentheaders { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)..., Referer: https://quote.eastmoney.com/ }5.2 请求频率控制太快的请求频率可能会被限制建议加上延时import time def crawl_with_delay(url): time.sleep(1) # 1秒延时 return requests.get(url, headersheaders)5.3 代理IP池如果要做大规模爬取建议使用代理IPproxies { http: http://your_proxy:port, https: http://your_proxy:port } response requests.get(url, headersheaders, proxiesproxies)6. 完整代码示例把上面的各部分组合起来完整的爬虫代码如下import requests import re import pandas as pd import time headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)..., Referer: https://quote.eastmoney.com/ } market_map { 沪深京A股: f3fsm:0t:6,m:0t:80,m:1t:2,m:1t:23,m:0t:81s:2048, # 其他板块... } def parse_jsonp(jsonp_str): left_data re.search(r^.*?(?\(), jsonp_str).group() data re.sub(left_data \(, , jsonp_str) data re.sub(\);, , data) return data def crawl_market(market_name, market_code): page 1 all_data [] null null while True: url fhttps://7.push2.eastmoney.com/api/qt/clist/get?...pn{page}pz20fid{market_code} response requests.get(url, headersheaders) data eval(parse_jsonp(response.text)) if data[data] null: break for item in data[data][diff]: cleaned { 代码: item[f12], 名称: item[f14], 最新价: item[f2], # 其他字段... } all_data.append(cleaned) print(f已爬取{market_name}第{page}页) page 1 time.sleep(1) return all_data # 主程序 for name, code in market_map.items(): print(f开始爬取{name}...) data crawl_market(name, code) save_to_excel(data, f{name}_股票数据.xlsx) print(f{name}数据已保存)7. 常见问题与解决方案在实际使用中可能会遇到这些问题数据获取不全检查分页逻辑是否正确确认请求参数是否完整查看是否有反爬限制请求被拒绝检查请求头设置尝试更换User-Agent添加Referer字段数据解析错误确认JSONP解析逻辑检查字段映射关系处理可能的空值情况性能优化使用多线程/异步请求合理设置请求间隔考虑使用缓存机制我在实际项目中还遇到过字段突然变更的情况所以建议定期检查接口返回的数据结构最好能加上一些数据校验逻辑。