利用Python获取京沪深历史数据并导入数据库
1、模块说明
akshare:基于 Python 的开源财经数据接口库,旨在为金融研究、量化交易等领域提供 股票、期货、期权、基金、外汇、债券、指数、加密货币 等金融产品的 实时数据、历史行情数据及衍生数据,支持从数据采集、清洗到存储的全流程处理
sqlalchemy:Python 中最流行的 ORM(对象关系映射)库 和 SQL 工具包,它允许开发者通过 Python 类和方法操作数据库,而无需直接编写原始 SQL 语句。其核心目标是提供高效、灵活且安全的数据库访问方式。
2、数据库表
CREATE TABLE `stocks_qfq` (
`id` int primary key auto_increment,
`trade_date` date DEFAULT NULL COMMENT '交易日',
`symbol` varchar(10) NOT NULL COMMENT '股票代码',
`name` varchar(10) NOT NULL COMMENT '公司名称',
`px_close_last` decimal(10,2) DEFAULT NULL COMMENT '昨日收盘价',
`px_open` decimal(10,2) DEFAULT NULL COMMENT '开盘价',
`px_close` decimal(10,2) DEFAULT NULL COMMENT '收盘价',
`high` decimal(10,2) DEFAULT NULL COMMENT '当日最高价',
`low` decimal(10,2) DEFAULT NULL COMMENT '当日最低价',
`vol` bigint DEFAULT NULL COMMENT '成交量(股)',
`amt` bigint DEFAULT NULL COMMENT '成交额(元)',
`amplitude` decimal(5,4) DEFAULT NULL COMMENT '振幅(百分比)',
`pct_chg` decimal(5,4) DEFAULT NULL COMMENT '涨跌幅(百分比)',
`chg_amt` decimal(10,2) DEFAULT NULL COMMENT '涨跌额(绝对值)',
`turnover` decimal(5,4) DEFAULT NULL COMMENT '换手率(百分比)'
);
3、Python代码
import time
from sqlalchemy import create_engine, Table, Column, MetaData, Numeric, Date, String, Integer
from sqlalchemy.dialects.mysql import NUMERIC
import akshare as ak
import pandas as pd
from urllib.parse import quote
from datetime import datetime
# ================== 数据库配置 ==================
DB_USER = "user"
DB_PASSWORD = "123456@mysql"
encoded_password = quote(DB_PASSWORD) # 自动转义特殊字符(如@转为%40)
DB_HOST = "192.168.10.27" # 或你的数据库IP
DB_NAME = "stocks"
TABLE_NAME = "stocks_hfq"
# 创建数据库引擎
engine = create_engine(f"mysql+pymysql://{DB_USER}:{encoded_password}@{DB_HOST}/{DB_NAME}")
# ================== 定义表结构(需与数据库实际表一致) ==================
metadata = MetaData()
Stock_daily = Table(
"stocks_hfq",
metadata,
Column("id", Integer), # 建议改为自增主键:Column("id", Integer, primary_key=True, autoincrement=True)
Column("trade_date", Date),
Column("symbol", String(10)),
Column("name", String(10)),
Column("px_open", Numeric(10, 2)),
Column("px_close", Numeric(10, 2)),
Column("high", Numeric(10, 2)),
Column("low", Numeric(10, 2)),
Column("vol", Numeric),
Column("amt", Numeric(15, 2)),
Column("amplitude", Numeric(5, 2)),
Column("pct_chg", Numeric(5, 2)),
Column("chg_amt", Numeric(10, 2)),
Column("turnover", Numeric(5, 2))
)
# ================== 获取股票列表 ==================
def get_stock_list():
"""获取沪深京A股代码列表"""
stock_list = ak.stock_zh_a_spot_em()
return stock_list[["代码", "名称"]]
# ================== 主逻辑:遍历股票并插入数据 ==================
def insert_stock_daily_data():
stock_list = get_stock_list()
i=0
for idx, row in stock_list.iterrows():
stock_code = row["代码"]
stock_name = row["名称"]
try:
# 从akshare获取历史数据(假设使用后复权)
df = ak.stock_zh_a_hist(
symbol=stock_code,
period="daily",
adjust="hfq" # 可选:"qfq"(前复权)或 None(不复权)
)
#print(df.head())
# 添加股票代码和名称列
#df["symbol"] = stock_code
df["name"] = stock_name
df["振幅"]=df["振幅"]/100 #换算为百分比
df["涨跌幅"]=df["涨跌幅"]/100 #换算为百分比
df["换手率"]=df["换手率"]/100 #换算为百分比
df["昨收"]=df["收盘"] / (1 + df["涨跌幅"]) #换算昨日收盘价
# 重命名列(映射到表结构)
df = df.rename(columns={
"日期": "trade_date",
"股票代码": "symbol",
"名称": "name",
"昨收": "px_close_last",
"开盘": "px_open",
"收盘": "px_close",
"最高": "high",
"最低": "low",
"成交量": "vol",
"成交额": "amt",
"振幅": "amplitude",
"涨跌幅": "pct_chg",
"涨跌额": "chg_amt",
"换手率": "turnover"
})
# 转换日期格式(确保为 datetime.date 类型)
df["trade_date"] = pd.to_datetime(df["trade_date"]).dt.date
# 插入数据库(自动匹配列名)
df.to_sql(
name=TABLE_NAME,
con=engine,
if_exists="append",
index=False,
dtype={
"trade_date": Date,
"symbol": String(10),
"name": String(10),
"px_open": NUMERIC(10, 2),
"px_close": NUMERIC(10, 2),
"high": NUMERIC(10, 2),
"low": NUMERIC(10, 2),
"vol": NUMERIC,
"amt": NUMERIC(15, 2),
"amplitude": NUMERIC(5, 2),
"pct_chg": NUMERIC(5, 2),
"chg_amt": NUMERIC(10, 2),
"turnover": NUMERIC(5, 2)
}
)
print(f"插入成功: {stock_code} {stock_name}")
time.sleep(10)
except Exception as e:
print(f"错误: {stock_code} {stock_name}", str(e))
time.sleep(10) #限制请求频率,避免触发反爬虫机制
if __name__ == "__main__":
insert_stock_daily_data()
4、补充说明
sqlalchemy中数据类型定义与mysql或其他RDMS不一样,以下是sqlalchemy常用基础数据类型:
from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime, Date, Float, Numeric
class User(Base):
__tablename__ = "users"
# 整数类型
id = Column(Integer, primary_key=True)
# 字符串类型(带长度限制)
name = Column(String(50), nullable=False)
# 长文本(无长度限制)
description = Column(Text)
# 布尔类型(映射为数据库的 TINYINT/BOOLEAN)
is_active = Column(Boolean, default=True)
# 日期时间类型
created_at = Column(DateTime, default=datetime.now)
# 日期类型
birth_date = Column(Date)
# 浮点数(近似值)
price = Column(Float)
# 高精度小数(适合金额)
balance = Column(Numeric(10, 2)) # 总位数 10,小数位 2
浙公网安备 33010602011771号