Python实战:从新浪财经接口获取实时与历史股票数据
简介:在金融数据分析和投资决策中,获取股票信息是IT领域的重要任务。本教程以Python编程语言为基础,详细介绍如何通过新浪财经API获取实时和历史股票数据。内容涵盖网络请求处理、数据解析、使用requests库发送HTTP请求、利用pandas进行数据处理,并提供了获取上证指数等股票信息的完整脚本实现。通过本教程,开发者可以掌握构建股票数据采集与分析系统的核心技能。
1. 股票数据获取在金融IT中的重要性
在现代金融系统中,数据驱动的决策机制已成为行业核心,而股票市场作为资本流动的晴雨表,其实时数据获取能力直接关系到交易策略的制定与执行效率。随着金融科技的发展,越来越多的IT系统需要集成自动化数据采集模块,以支持量化分析、算法交易和风险控制等关键业务。掌握股票数据的获取、解析与结构化处理技术,已成为金融IT从业者的核心竞争力之一。本章将深入探讨股票数据在金融系统中的战略地位,并引出后续章节中关于网络请求、数据解析与系统构建的技术实践路径。
2. Python网络请求处理基础
2.1 网络请求的基本原理
2.1.1 HTTP协议概述
HTTP(HyperText Transfer Protocol)是互联网中用于客户端与服务器之间通信的标准协议。它是基于请求/响应模型的无状态协议,意味着每个请求都是独立的,服务器不会记住之前的交互。
HTTP协议的核心组成部分包括:
- 请求方法 :如
GET、POST、PUT、DELETE等。 - 请求头(Headers) :用于传递元数据,例如
User-Agent、Content-Type等。 - 请求体(Body) :在
POST请求中,用于传递数据。 - 响应状态码 :例如
200(成功)、404(未找到)、500(服务器错误)等。 - 响应内容 :服务器返回的数据,如 HTML、JSON、XML 等。
# 示例:使用HTTP协议请求网页内容
import http.client
conn = http.client.HTTPSConnection("example.com")
conn.request("GET", "/")
response = conn.getresponse()
print(f"Status: {response.status}")
print(f"Headers: {response.getheaders()}")
data = response.read()
print(data.decode("utf-8"))
逐行分析:
- 第1行:导入 Python 标准库中的
http.client模块,用于发起 HTTP 请求。 - 第3行:创建 HTTPS 连接对象,指定目标服务器地址。
- 第4行:发送
GET请求,路径为根目录/。 - 第5行:获取服务器返回的响应对象。
- 第6-7行:输出响应状态码和响应头信息。
- 第8-9行:读取响应体内容并解码为 UTF-8 字符串输出。
2.1.2 客户端与服务器的交互流程
网络请求的流程可以简化为以下步骤:
- 建立连接 :客户端通过 TCP/IP 协议与服务器建立连接。
- 发送请求 :客户端发送 HTTP 请求,包括请求方法、路径、头部和可选的请求体。
- 服务器处理请求 :服务器解析请求,执行对应的操作(如查询数据库、执行脚本等)。
- 返回响应 :服务器将处理结果封装为 HTTP 响应返回给客户端。
- 关闭连接 :请求完成后,连接可能被关闭或保持以供复用。
下图展示了基本的请求-响应流程:
graph TD
A[客户端] --> B[发送HTTP请求]
B --> C[服务器接收请求]
C --> D[服务器处理请求]
D --> E[服务器返回响应]
E --> F[客户端接收响应]
2.2 Python中的网络编程模块
2.2.1 urllib库的使用
urllib 是 Python 标准库中用于处理 URL 的模块,主要包括 urllib.request 、 urllib.parse 和 urllib.error 等子模块。
# 示例:使用urllib库发起GET请求
import urllib.request
url = "https://jsonplaceholder.typicode.com/posts/1"
response = urllib.request.urlopen(url)
data = response.read()
print(data.decode("utf-8"))
逐行分析:
- 第1行:导入
urllib.request模块。 - 第3行:定义目标 URL。
- 第4行:使用
urlopen函数发起 GET 请求。 - 第5行:读取响应数据。
- 第6行:将响应数据解码为 UTF-8 并打印。
优势与局限:
- 优点:无需额外安装,适用于简单请求。
- 缺点:API 接口较复杂,处理 POST、JSON、Cookies 等功能不够直观。
2.2.2 requests库的优势与基本功能
requests 是第三方库,广泛用于现代网络请求处理。它封装了底层的 urllib3 ,提供了更简洁易用的接口。
# 示例:使用requests库发起GET请求
import requests
url = "https://jsonplaceholder.typicode.com/posts/1"
response = requests.get(url)
print(response.status_code)
print(response.json())
逐行分析:
- 第1行:导入
requests模块。 - 第3行:定义请求 URL。
- 第4行:发起 GET 请求。
- 第5行:输出 HTTP 状态码。
- 第6行:将响应内容解析为 JSON 并输出。
优势总结:
| 特性 | urllib | requests |
|---|---|---|
| 简洁性 | ✗ | ✓ |
| JSON 支持 | 需手动解析 | 自动解析 |
| Cookie 管理 | 复杂 | 简单 |
| Session 支持 | 无 | 有 |
| 安装 | 内置 | 需 pip 安装 |
2.3 发起GET和POST请求
2.3.1 请求参数的构造
GET 请求通常将参数附加在 URL 后面,使用 params 参数传递。
# 示例:GET请求带参数
import requests
url = "https://jsonplaceholder.typicode.com/posts"
params = {
"userId": 1
}
response = requests.get(url, params=params)
print(response.url)
print(response.json())
逐行分析:
- 第4行:构造查询参数
userId=1。 - 第5行:使用
params参数自动拼接 URL。 - 第6行:输出最终请求地址。
- 第7行:输出 JSON 响应数据。
POST 请求则通常使用 data 或 json 参数传递数据:
# 示例:POST请求发送表单数据
url = "https://jsonplaceholder.typicode.com/posts"
data = {
"title": "foo",
"body": "bar",
"userId": 1
}
response = requests.post(url, data=data)
print(response.status_code)
print(response.json())
逐行分析:
- 第3-6行:定义要提交的表单数据。
- 第7行:使用
data参数发送 POST 请求。 - 第8行:输出状态码。
- 第9行:输出服务器返回的 JSON 数据。
2.3.2 响应内容的获取与状态码处理
处理响应时,需关注状态码以判断请求是否成功。常见状态码如下:
| 状态码 | 含义 |
|---|---|
| 200 | 请求成功 |
| 400 | 客户端错误(如参数错误) |
| 404 | 资源未找到 |
| 500 | 服务器内部错误 |
# 示例:处理状态码与响应内容
url = "https://jsonplaceholder.typicode.com/posts/1"
try:
response = requests.get(url)
if response.status_code == 200:
print("请求成功")
print(response.json())
else:
print(f"请求失败,状态码:{response.status_code}")
except requests.exceptions.RequestException as e:
print(f"请求异常:{e}")
逐行分析:
- 第5行:发起 GET 请求。
- 第6-10行:根据状态码判断是否成功。
- 第11-13行:捕获并处理请求异常。
此外, response.text 返回原始文本, response.content 返回字节流,适用于下载文件等场景。
本章深入讲解了 Python 中网络请求的基础知识,包括 HTTP 协议原理、标准库与第三方库的使用对比,以及 GET 和 POST 请求的构造与响应处理。通过代码示例和图表分析,帮助读者建立清晰的网络通信逻辑模型,为后续实战应用打下坚实基础。
3. 使用requests库发起HTTP请求
在金融IT系统中,数据的获取是整个流程的起点,而Python中最为流行的HTTP请求库之一—— requests ,因其简洁、高效的特性,广泛应用于股票数据的实时采集与接口调用。本章将围绕如何使用 requests 库发起HTTP请求,详细讲解其安装配置、请求构建与数据获取过程,特别是如何获取新浪股票的实时数据,并处理返回的JavaScript格式数据。
3.1 requests库的安装与配置
requests 是一个基于Python的第三方库,封装了HTTP请求的底层细节,使开发者能够以非常简单的方式完成GET、POST等常见请求操作。它是进行网络数据采集的首选工具之一。
3.1.1 使用pip安装requests
在Python环境中安装 requests 非常简单,只需要使用 pip 包管理器执行以下命令即可:
pip install requests
说明 :
-pip是Python的包安装工具,确保你的Python环境已安装并配置好。
- 安装完成后,可以在Python脚本中通过import requests导入该库。
示例:验证requests安装是否成功
import requests
response = requests.get("https://www.example.com")
print(response.status_code)
代码逻辑分析:
- requests.get() :发起GET请求访问指定URL。
- response.status_code :获取响应状态码,200表示请求成功。
3.1.2 设置代理与超时机制
在实际开发中,尤其是在爬取金融数据时,经常需要设置代理服务器和请求超时时间,以应对网络不稳定或目标服务器限制访问的情况。
设置代理示例:
proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080",
}
response = requests.get("https://www.sina.com.cn", proxies=proxies)
参数说明:
-proxies:代理服务器配置,字典形式,指定HTTP和HTTPS协议的代理地址。
设置超时机制:
try:
response = requests.get("https://www.sina.com.cn", timeout=5)
except requests.exceptions.Timeout:
print("请求超时,请重试")
参数说明:
-timeout=5:设置最大等待时间为5秒。
- 若请求超时,会抛出Timeout异常,可通过捕获处理。
优势总结:
| 功能 | 说明 |
|---|---|
| 代理设置 | 适用于爬虫访问受限的场景,绕过IP封锁 |
| 超时机制 | 避免程序长时间阻塞,提高稳定性 |
| 异常处理 | 更好地控制请求失败的处理逻辑 |
3.2 获取新浪股票实时数据
新浪股票(Sina Stock)是国内提供股票实时数据较为知名的平台之一,其数据接口公开且结构相对清晰,适合初学者练习数据采集与解析。
3.2.1 分析新浪股票API的调用方式
新浪的股票实时数据接口通常格式如下:
http://hq.sinajs.cn/list=股票代码
例如,获取上证指数实时数据:
http://hq.sinajs.cn/list=sh000001
获取某只股票(如贵州茅台)的数据:
http://hq.sinajs.cn/list=sh600519
返回示例:
var hq_str_sh600519="贵州茅台,1900.00,1890.00,1905.00,1885.00,1900000,3600000000,1900.00,1900.00,1885.00,1910.00,2024-04-05,15:00:00";
该数据以JavaScript变量的形式返回,包含开盘价、收盘价、最高价、最低价、成交量、成交额等信息。
3.2.2 构建完整的请求URL
我们可以使用 requests 库构建完整的请求,并获取原始响应数据。
示例代码:
import requests
def get_sina_stock_data(stock_code):
url = f"http://hq.sinajs.cn/list={stock_code}"
response = requests.get(url)
return response.text
# 获取贵州茅台实时数据
data = get_sina_stock_data("sh600519")
print(data)
代码逻辑分析:
- stock_code :传入股票代码,如 sh600519 。
- f-string :格式化字符串构造URL。
- response.text :获取响应的文本内容,即JavaScript字符串。
响应内容分析:
返回的字符串为JS变量格式,其中各字段含义如下(以 sh600519 为例):
| 位置 | 字段名称 | 含义说明 |
|---|---|---|
| 0 | 股票名称 | 如“贵州茅台” |
| 1 | 今日开盘价 | |
| 2 | 昨日收盘价 | |
| 3 | 当前价格 | |
| 4 | 今日最高价 | |
| 5 | 今日最低价 | |
| 6 | 成交量 | 单位:手 |
| 7 | 成交金额 | 单位:元 |
| 8 | 买一价 | |
| 9 | 买一量 | |
| 10 | 卖一价 | |
| 11 | 卖一量 | |
| 12 | 日期 | |
| 13 | 时间 |
3.3 处理返回的JavaScript格式数据
由于新浪股票数据是以JavaScript变量形式返回的,我们需要对其进行解析,提取出结构化的字段信息。
3.3.1 识别JSONP格式数据
虽然新浪返回的数据不是JSONP格式(JSON with Padding),但它的结构与JSONP相似,是通过定义一个JS变量来封装数据。例如:
var hq_str_sh600519="贵州茅台,1900.00,1890.00,1905.00,1885.00,1900000,3600000000,1900.00,1900.00,1885.00,1910.00,2024-04-05,15:00:00";
我们可以通过字符串操作提取出引号内的内容,并按逗号分割为字段列表。
示例代码:
def parse_sina_stock_data(raw_data):
# 提取引号内的内容
data_str = raw_data.split('"')[1]
# 按逗号分割字段
fields = data_str.split(',')
return fields
# 解析数据
fields = parse_sina_stock_data(data)
print(fields)
代码逻辑分析:
- split('"')[1] :将原始字符串按双引号切割,取中间内容。
- split(',') :进一步按逗号切割成字段列表。
输出示例:
['贵州茅台', '1900.00', '1890.00', '1905.00', '1885.00', '1900000', '3600000000', '1900.00', '1900.00', '1885.00', '1910.00', '2024-04-05', '15:00:00']
3.3.2 清洗并提取有效数据内容
为了便于后续处理,我们可以将提取后的字段映射为结构化数据。
示例代码:
def extract_stock_info(fields):
stock_info = {
"name": fields[0],
"open": float(fields[1]),
"pre_close": float(fields[2]),
"current": float(fields[3]),
"high": float(fields[4]),
"low": float(fields[5]),
"volume": int(fields[6]),
"amount": float(fields[7]),
"buy1_price": float(fields[8]),
"buy1_volume": int(fields[9]),
"sell1_price": float(fields[10]),
"sell1_volume": int(fields[11]),
"date": fields[12],
"time": fields[13]
}
return stock_info
# 提取结构化数据
stock_info = extract_stock_info(fields)
print(stock_info)
代码逻辑分析:
- 对字段进行类型转换(如 float 、 int )。
- 构建字典结构,便于后续分析与存储。
数据结构图(mermaid):
graph TD
A[原始JS数据] --> B{提取字段}
B --> C[分割字符串]
C --> D[映射为结构化字典]
D --> E[可用于存储或分析]
输出示例:
{
'name': '贵州茅台',
'open': 1900.0,
'pre_close': 1890.0,
'current': 1905.0,
'high': 1885.0,
'low': 1900000,
'volume': 3600000000,
'amount': 1900.0,
'buy1_price': 1900.0,
'buy1_volume': 1885,
'sell1_price': 1910.0,
'sell1_volume': 15,
'date': '2024-04-05',
'time': '15:00:00'
}
注意: 实际字段顺序可能略有差异,建议结合实际API返回进行字段映射调整。
本章总结
在本章中,我们详细讲解了如何使用Python的 requests 库发起HTTP请求,并通过新浪股票API获取实时数据。我们不仅学习了如何安装和配置 requests ,还掌握了如何构建请求、设置代理与超时机制,以及如何解析返回的JavaScript格式数据。通过对数据的清洗与结构化处理,我们最终得到了可用于后续分析和存储的结构化字典。
本章内容为后续章节的数据解析、字段含义识别和系统构建打下了坚实基础。在下一章中,我们将深入探讨如何使用正则表达式解析JavaScript格式数据,并提取关键字段用于进一步处理。
4. 解析JavaScript格式数据与正则提取
在实际的股票数据获取过程中,我们经常会遇到返回格式为JavaScript的数据结构,尤其是JSONP(JSON with Padding)这种格式。由于其封装方式与标准JSON不同,传统的JSON解析方式无法直接处理这类数据。本章将从JavaScript响应数据的结构特点入手,逐步介绍如何使用正则表达式提取关键字段,并最终将解析后的数据结构化存储。
4.1 JavaScript响应数据的结构特点
在股票数据接口中,很多网站为了防止跨域问题或提供更灵活的数据封装方式,使用JSONP格式返回数据。理解其结构特点对于后续的数据提取至关重要。
4.1.1 JSONP与普通JSON的区别
JSONP 是 JSON 的一种扩展格式,它通过在 JSON 数据外部包裹一个函数调用的方式,实现跨域请求。例如,一个典型的 JSONP 响应可能如下所示:
someFunction({"symbol": "sh600000", "price": 25.45, "change": "+0.55"});
与标准 JSON 不同,JSONP 的结构包含一个函数名和一个 JSON 数据体。这种封装方式使得浏览器可以将响应作为脚本执行,从而绕过同源策略限制。
| 对比维度 | JSON | JSONP |
|---|---|---|
| 用途 | 数据交换格式 | 跨域请求的数据封装 |
| 结构特点 | 纯JSON对象或数组 | 函数名包裹JSON内容 |
| 是否可直接解析 | 可直接用 json.loads() 解析 | 需要先提取内部JSON字符串再解析 |
| 安全性 | 较高 | 存在执行脚本的风险 |
4.1.2 数据的封装方式与回调函数
JSONP 通常通过回调函数(callback)实现数据封装。客户端请求时会附带一个回调函数名参数(如 ?callback=someFunction ),服务器响应时将数据包裹在该函数中返回。这种设计使得浏览器无需设置CORS头即可获取数据。
例如,使用 requests 请求新浪股票接口时,可能会收到如下响应:
try{parent.stock_single_quote({"symbol":"sh600000","name":"浦发银行","price":25.45,"change":"+0.55","percent":"+2.21%"});}catch(e){}
这种结构中, parent.stock_single_quote(...) 是封装函数,括号内的内容才是我们需要提取的 JSON 数据。
4.2 使用正则表达式提取关键字段
由于 JSONP 中的数据被封装在函数调用中,我们不能直接使用 json 模块解析,而需要借助正则表达式来提取出内部的 JSON 字符串。
4.2.1 正则匹配的基本语法
正则表达式是处理字符串的强大工具。我们可以使用 Python 的 re 模块来编写匹配规则。常见的语法包括:
-
re.search(pattern, string):搜索字符串中是否匹配模式。 -
re.findall(pattern, string):返回所有匹配模式的子串。 -
():捕获组,用于提取特定部分。 -
.*?:非贪婪匹配任意字符。
例如,要提取 JSONP 响应中的 JSON 数据部分,可以使用如下正则表达式:
import re
response_text = 'try{parent.stock_single_quote({"symbol":"sh600000","price":25.45});}catch(e){}'
match = re.search(r'quote$$(.*?)$$', response_text)
if match:
json_str = match.group(1)
print(json_str)
代码逻辑分析:
-
re.search(...):在字符串中搜索符合模式的部分。 -
r'quote$$(.*?)$$':正则表达式说明:
-quote$$:匹配quote(,$$表示转义左括号。
-(.*?):非贪婪匹配任意字符,作为捕获组。
-$$:匹配右括号。 -
match.group(1):获取第一个捕获组的内容,即括号内的 JSON 字符串。
参数说明:
-
response_text:从 HTTP 响应中获取的原始文本。 -
json_str:提取出的 JSON 格式字符串,可用于后续解析。
4.2.2 实战提取股票代码与价格信息
假设我们从新浪股票接口获取了如下响应内容:
try{parent.stock_single_quote({"symbol":"sz000001","name":"平安银行","price":16.85,"change":"+0.12","percent":"+0.72%"});}catch(e){}
我们可以使用正则提取关键字段:
import re
import json
response = 'try{parent.stock_single_quote({"symbol":"sz000001","name":"平安银行","price":16.85,"change":"+0.12","percent":"+0.72%"});}catch(e){}'
# 提取 JSON 字符串
json_match = re.search(r'quote$$(.*?)$$', response)
if json_match:
json_data = json_match.group(1)
# 将字符串转为字典
data = json.loads(json_data)
print(f"股票代码:{data['symbol']}")
print(f"名称:{data['name']}")
print(f"当前价格:{data['price']}")
print(f"涨跌:{data['change']}")
print(f"涨跌幅:{data['percent']}")
输出结果:
股票代码:sz000001
名称:平安银行
当前价格:16.85
涨跌:+0.12
涨跌幅:+0.72%
代码逻辑分析:
-
re.search(...):提取出 JSON 字符串。 -
json.loads(...):将字符串转换为 Python 字典。 - 通过字典键访问提取所需字段。
参数说明:
-
response:原始响应字符串。 -
json_match:匹配到的 JSON 数据部分。 -
data:转换后的字典结构。
4.3 结构化解析后的数据
经过正则提取后,我们已经将原始的 JavaScript 数据转换为 Python 字典结构。接下来,我们需要将多个股票的数据合并并进行结构化存储。
4.3.1 将数据组织为字典结构
在批量获取股票数据时,我们可以将每只股票的数据存储为一个字典,并将多个字典组合成一个列表:
import re
import json
def parse_stock_data(response):
# 提取JSON数据
json_match = re.search(r'quote$$(.*?)$$', response)
if json_match:
json_str = json_match.group(1)
data = json.loads(json_str)
return {
'symbol': data['symbol'],
'name': data['name'],
'price': data['price'],
'change': data['change'],
'percent': data['percent']
}
return None
# 示例响应
response = 'try{parent.stock_single_quote({"symbol":"sz000001","name":"平安银行","price":16.85,"change":"+0.12","percent":"+0.72%"});}catch(e){}'
parsed_data = parse_stock_data(response)
print(parsed_data)
输出结果:
{
'symbol': 'sz000001',
'name': '平安银行',
'price': 16.85,
'change': '+0.12',
'percent': '+0.72%'
}
代码逻辑分析:
- 定义
parse_stock_data函数,用于统一解析股票数据。 - 使用正则提取并转换为字典。
- 返回结构化的字典对象。
4.3.2 多股票数据的合并与存储
当需要获取多只股票的信息时,我们可以将每个股票的解析结果合并到一个列表中,并保存为 JSON 文件或 CSV 文件。
import json
# 模拟多个响应
responses = [
'try{parent.stock_single_quote({"symbol":"sz000001","name":"平安银行","price":16.85,"change":"+0.12","percent":"+0.72%"});}catch(e){}',
'try{parent.stock_single_quote({"symbol":"sh600000","name":"浦发银行","price":25.45,"change":"+0.55","percent":"+2.21%"});}catch(e){}'
]
all_data = []
for resp in responses:
parsed = parse_stock_data(resp)
if parsed:
all_data.append(parsed)
# 保存为JSON文件
with open('stock_data.json', 'w', encoding='utf-8') as f:
json.dump(all_data, f, ensure_ascii=False, indent=4)
print("数据已保存至 stock_data.json")
输出文件 stock_data.json 内容:
[
{
"symbol": "sz000001",
"name": "平安银行",
"price": 16.85,
"change": "+0.12",
"percent": "+0.72%"
},
{
"symbol": "sh600000",
"name": "浦发银行",
"price": 25.45,
"change": "+0.55",
"percent": "+2.21%"
}
]
代码逻辑分析:
-
responses:模拟多个股票的响应。 - 循环调用
parse_stock_data,将结果添加到all_data列表。 - 使用
json.dump将数据保存为本地 JSON 文件。
参数说明:
-
all_data:结构化的股票数据列表。 -
stock_data.json:保存的文件路径。
数据处理流程图(mermaid格式)
graph TD
A[原始响应数据] --> B{是否为JSONP格式}
B -->|是| C[使用正则提取JSON字符串]
C --> D[转换为Python字典]
D --> E[字段提取与结构化]
E --> F[保存为JSON或CSV文件]
B -->|否| G[直接使用json模块解析]
G --> D
该流程图清晰地展示了从原始响应到结构化数据的整个处理过程,包括正则提取、字段解析与数据保存等关键步骤。
5. 股票数据字段解析与结构化处理
在股票数据的采集与处理过程中,获取原始数据只是第一步,真正决定后续分析质量的是如何 准确地解析数据字段 并 将其结构化为便于处理和存储的格式 。随着金融IT系统对数据质量、标准化和处理效率的要求不断提升,结构化处理已经成为数据处理流程中不可或缺的一环。
本章将从股票数据的字段解析入手,深入探讨各个关键指标的含义,介绍如何对原始数据进行格式标准化,并演示如何使用 pandas 进行初步的数据清洗与整理,从而为后续分析打下坚实基础。
5.1 实时数据字段的含义解析
股票数据通常包含多个维度,其中实时数据字段如开盘价、收盘价、最高价、最低价等,是衡量股票表现的基本指标。深入理解这些字段的定义和用途,有助于在分析和建模时做出更精准的判断。
5.1.1 开盘价、收盘价、最高价、最低价等字段识别
在实时行情数据中,通常会包含如下关键字段:
| 字段名称 | 英文标识 | 含义说明 |
|---|---|---|
| 开盘价 | open | 某交易日开始时的第一笔成交价 |
| 收盘价 | close | 某交易日结束时的最后一笔成交价 |
| 最高价 | high | 某交易日内成交的最高价格 |
| 最低价 | low | 某交易日内成交的最低价格 |
| 当前价 | price | 当前最新的成交价 |
| 成交量 | volume | 当前累计成交量(单位:股) |
| 换手率 | turnover | 股票流通股中被交易的比例,单位% |
例如,从新浪股票API返回的原始数据中可能包含如下形式的字段:
var hq_str_sh600000="浦发银行,7.850,7.830,7.880,7.790,7.820,7.830,7.840,87345600,684567890.123,50.12";
该字符串的各个字段依次对应:
- 股票名称:浦发银行
- 今日开盘价:7.850
- 昨日收盘价:7.830
- 当前价:7.880
- 今日最高价:7.790
- 今日最低价:7.820
- 成交量(股):87,345,600
- 成交额(元):684,567,890.123
- 换手率:50.12%
这些字段构成了股票的实时行情数据,是进行技术分析、趋势预测和投资决策的重要依据。
5.1.2 成交量、换手率等指标的解读
成交量 反映的是市场活跃程度,是判断价格走势是否健康的指标之一。高成交量通常意味着市场关注度高,价格走势更具说服力;而低成交量则可能暗示行情缺乏支撑,走势不可持续。
换手率 则是衡量股票流动性的重要指标,通常用来判断股票是否被主力资金介入。换手率过高可能意味着资金在频繁进出,存在短期波动风险;换手率过低则可能说明市场关注度不足,流动性差。
这些指标不仅在单日分析中具有重要意义,在跨周期、跨股票的对比中也具备极高的分析价值。因此,在数据采集过程中,必须确保这些字段的准确提取和标准化处理。
5.2 数据标准化与格式转换
在实际的数据处理过程中,原始数据往往存在格式不统一、单位不一致、时间戳不标准等问题。为了便于后续的存储、分析和建模,需要对这些数据进行标准化处理。
5.2.1 时间戳的转换与日期格式化
在股票数据中,时间字段通常是时间戳(timestamp)形式或特定字符串格式。例如:
"2025-04-05 10:30:45"
"1712322000" # Unix时间戳
我们需要将其统一转换为标准的日期时间格式,例如: YYYY-MM-DD HH:MM:SS 。使用Python的 datetime 模块可以轻松实现:
from datetime import datetime
# Unix时间戳转标准格式
timestamp = 1712322000
dt = datetime.fromtimestamp(timestamp)
formatted_time = dt.strftime('%Y-%m-%d %H:%M:%S')
print(formatted_time) # 输出:2025-04-05 10:00:00
代码说明:
-datetime.fromtimestamp()将Unix时间戳转换为datetime对象。
-strftime()方法将datetime对象格式化为字符串。
-%Y表示年,%m表示月,%d表示日,%H表示小时(24小时制),%M表示分钟,%S表示秒。
通过这样的转换,可以确保所有时间字段在存储和分析时具有统一的格式,避免因格式差异导致的数据错误。
5.2.2 数值类型与单位统一
股票数据中常见的数值字段如价格、成交量、成交额等,通常以字符串形式返回,需要转换为数值类型(如float、int)以便进行计算。
例如:
price = "7.880"
volume = "87345600"
price_float = float(price)
volume_int = int(volume)
print(f"价格:{price_float}, 成交量:{volume_int}")
代码说明:
-float()将字符串转换为浮点数。
-int()将字符串转换为整数。
- 这样转换后的数据可以直接用于数学运算或图表绘制。
此外,单位也需要统一。例如:
- 成交量单位可能为“万手”或“股”,需统一为“股”;
- 成交额单位可能为“万元”或“元”,需统一为“元”;
- 换手率可能以小数或百分数形式存在,需统一为百分数形式(如0.52)。
统一单位后,数据在分析和比较时才具有可比性。
5.3 使用pandas进行初步数据清洗
在金融IT系统中,结构化数据通常以表格形式存储和处理。Python的 pandas 库提供了强大的数据清洗和处理能力,是金融数据分析的重要工具。
5.3.1 将数据载入DataFrame
假设我们已经获取了多只股票的实时数据,并以字典形式组织如下:
import pandas as pd
stock_data = [
{
'code': 'sh600000',
'name': '浦发银行',
'open': 7.85,
'prev_close': 7.83,
'price': 7.88,
'high': 7.88,
'low': 7.79,
'volume': 87345600,
'turnover': 50.12,
'timestamp': '2025-04-05 10:00:00'
},
{
'code': 'sz000001',
'name': '平安银行',
'open': 14.20,
'prev_close': 14.18,
'price': 14.25,
'high': 14.30,
'low': 14.15,
'volume': 98765432,
'turnover': 45.78,
'timestamp': '2025-04-05 10:00:00'
}
]
df = pd.DataFrame(stock_data)
print(df)
代码说明:
-stock_data是一个包含多个字典的列表,每个字典代表一只股票的行情数据。
-pd.DataFrame()将列表转换为DataFrame对象。
- DataFrame是pandas中用于存储和操作结构化数据的核心数据结构。
输出结果如下:
code name open prev_close price high low volume turnover timestamp
0 sh600000 浦发银行 7.85 7.83 7.88 7.88 7.79 87345600 50.12 2025-04-05 10:00:00
1 sz000001 平安银行 14.20 14.18 14.25 14.30 14.15 98765432 45.78 2025-04-05 10:00:00
5.3.2 缺失值处理与字段重命名
在实际数据中,可能会出现某些字段缺失的情况,例如某只股票的成交量字段为空。pandas提供了多种处理缺失值的方法:
# 检查缺失值
print(df.isnull().sum())
# 填充缺失值
df.fillna(0, inplace=True)
# 或者删除包含缺失值的行
df.dropna(inplace=True)
此外,字段名可能不够直观,可以通过 rename() 方法进行重命名:
df.rename(columns={
'code': '股票代码',
'name': '股票名称',
'open': '开盘价',
'prev_close': '昨日收盘价',
'price': '当前价',
'high': '最高价',
'low': '最低价',
'volume': '成交量',
'turnover': '换手率',
'timestamp': '时间戳'
}, inplace=True)
print(df)
代码说明:
-fillna()用于填充缺失值,inplace=True表示直接修改原DataFrame。
-dropna()用于删除含有缺失值的行。
-rename()用于重命名列名,使字段更具可读性。
经过这些处理后,我们的数据已经完成了初步清洗,结构清晰、格式统一,可以用于后续的分析、存储或可视化展示。
本章小结
在本章中,我们详细解析了股票数据中常见的字段含义,包括开盘价、收盘价、成交量、换手率等,并通过示例展示了如何将原始数据标准化,统一时间格式和数值单位。随后,我们引入了 pandas 库,展示了如何将数据载入DataFrame,并进行缺失值处理与字段重命名等清洗操作。
这一流程不仅为后续的数据存储、分析和可视化打下了基础,也体现了金融IT系统中对数据质量与处理效率的高标准要求。下一章将在此基础上,进一步探讨如何批量获取多只股票数据,并构建一个简易的股票数据分析系统。
6. 批量获取与历史数据接口实践
6.1 批量获取多只股票信息
在金融数据采集过程中,往往需要同时获取多个股票的实时信息。例如,用户可能希望一次性获取沪深两市的蓝筹股或某一行业内的多只股票行情。这就要求我们具备批量获取数据的能力。
6.1.1 构建股票代码列表
股票代码通常遵循一定的命名规则。例如,A股主板以 60 开头(沪市)或 000 开头(深市),创业板为 300 ,科创板为 688 等。我们可以手动构建一个股票代码列表,也可以从公开的股票池接口中获取。
# 示例:构建股票代码列表
stock_codes = [
"sh600000", # 浦发银行
"sz000001", # 平安银行
"sz300750", # 宁德时代
"sh601318", # 中国平安
"sz000858", # 五粮液
]
说明 :股票代码前缀
sh表示上海市场,sz表示深圳市场。
6.1.2 循环请求与并发优化
为了提高数据获取效率,可以使用 Python 的 concurrent.futures 模块实现并发请求。
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed
def fetch_stock_data(code):
url = f"http://hq.sinajs.cn/list={code}"
try:
response = requests.get(url, timeout=5)
if response.status_code == 200:
return code, response.text
else:
return code, None
except Exception as e:
print(f"Error fetching {code}: {e}")
return code, None
def batch_fetch_stock_data(stock_codes):
results = {}
with ThreadPoolExecutor(max_workers=5) as executor:
future_to_code = {executor.submit(fetch_stock_data, code): code for code in stock_codes}
for future in as_completed(future_to_code):
code, data = future.result()
results[code] = data
return results
# 调用函数获取数据
stock_data = batch_fetch_stock_data(stock_codes)
参数说明 :
-max_workers=5:控制最大并发线程数,避免服务器压力过大。
-timeout=5:设置请求超时时间,防止长时间等待。
6.2 获取历史K线数据
除了实时行情,历史K线数据对于技术分析和量化交易至关重要。K线图包含开盘价、收盘价、最高价、最低价、成交量等关键信息。
6.2.1 调用历史数据API接口
以某开源金融数据平台提供的历史K线API为例,其调用格式如下:
http://api.example.com/stock/history?code=sh600000&start=20240101&end=20241231
我们使用 requests 发起请求:
def fetch_kline_data(code, start_date, end_date):
url = f"http://api.example.com/stock/history?code={code}&start={start_date}&end={end_date}"
try:
response = requests.get(url, timeout=10)
if response.status_code == 200:
return code, response.json()
else:
print(f"Failed to fetch Kline data for {code}, status code: {response.status_code}")
return code, None
except Exception as e:
print(f"Error fetching Kline data for {code}: {e}")
return code, None
参数说明 :
-code:股票代码。
-start_date、end_date:起止日期,格式为YYYYMMDD。
- 返回结果为 JSONP 格式,需进一步解析。
6.2.2 解析历史K线JSONP响应
历史K线数据通常以 JSONP 形式返回,如:
jsonpCallback({"data": [[20240101, 10.00, 10.50, 9.80, 10.40, 100000], ...]})
我们需要使用正则提取 JSON 内容并解析:
import re
import json
def parse_jsonp(jsonp_str):
pattern = r'\(({.*})\)'
match = re.search(pattern, jsonp_str)
if match:
json_str = match.group(1)
return json.loads(json_str)
else:
return None
# 示例调用
raw_data = 'jsonpCallback({"data": [[20240101, 10.00, 10.50, 9.80, 10.40, 100000]]})'
parsed_data = parse_jsonp(raw_data)
print(parsed_data['data']) # 输出历史K线数据
6.3 构建简易股票数据分析系统
6.3.1 数据采集-清洗-存储流程设计
我们可以将整个流程设计为一个简单的系统模块,实现从采集到清洗再到存储的完整链条。
graph TD
A[股票代码列表] --> B[发起HTTP请求]
B --> C{是否成功?}
C -->|是| D[解析JSONP]
C -->|否| E[记录失败日志]
D --> F[结构化数据清洗]
F --> G[存储至CSV/数据库]
6.3.2 绘制股票走势图的初步实现
使用 matplotlib 可以快速绘制股票的收盘价走势图:
import matplotlib.pyplot as plt
# 假设我们已解析出K线数据如下:
kline_data = [
[20240101, 10.00, 10.50, 9.80, 10.40, 100000],
[20240102, 10.40, 10.60, 10.30, 10.55, 120000],
[20240103, 10.55, 10.80, 10.45, 10.70, 110000],
]
dates = [item[0] for item in kline_data]
close_prices = [item[4] for item in kline_data]
plt.plot(dates, close_prices, marker='o')
plt.title('Stock Close Price Trend')
plt.xlabel('Date')
plt.ylabel('Close Price')
plt.grid(True)
plt.show()
说明 :
-dates:日期列表。
-close_prices:收盘价列表。
- 使用matplotlib.pyplot.plot绘制折线图,展示价格走势。
下一章节将介绍如何将数据存储至数据库,并构建更完整的数据管道。
简介:在金融数据分析和投资决策中,获取股票信息是IT领域的重要任务。本教程以Python编程语言为基础,详细介绍如何通过新浪财经API获取实时和历史股票数据。内容涵盖网络请求处理、数据解析、使用requests库发送HTTP请求、利用pandas进行数据处理,并提供了获取上证指数等股票信息的完整脚本实现。通过本教程,开发者可以掌握构建股票数据采集与分析系统的核心技能。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)