在量化交易、股市分析、数据可视化等场景中,高质量的股票数据是核心基础。无论是实时盯盘的瞬时行情,还是用于回测的历史K线数据,都需要稳定、高效的获取方式。本文将从实时行情抓取、历史K线获取、数据存储、可视化分析、反爬应对五个核心维度,结合实战案例拆解股票数据获取的完整流程,涵盖API调用、网页爬虫两种主流方式,代码均经过实测验证,适合开发者直接复用。
一、环境准备:核心库安装
首先安装所需Python库,兼顾数据爬取、处理、存储与可视化:
# 基础爬取库
pip install requests==2.31.0 beautifulsoup4==4.12.3
# 数据处理库
pip install pandas==2.2.1 numpy==1.26.4
# 股票数据专用API库(免费)
pip install akshare==1.10.86 tushare==1.2.89
# 可视化库(绘制K线图)
pip install matplotlib==3.8.3 mplfinance==0.12.10b0
# 数据库存储库(可选)
pip install sqlite3 pymysql==1.1.0
关键库说明:
:免费开源的财经数据API,无需注册,支持实时行情、历史K线等,数据来源包括东方财富、同花顺等;
akshare:数据质量更高,覆盖全市场股票数据,但部分接口需要积分(注册后可免费获取基础积分);
tushare:专门用于绘制金融K线图,支持均线、成交量等指标集成;
mplfinance+
requests:用于网页爬虫,抓取公开网页的股票数据。
beautifulsoup4
二、实时行情数据抓取:两种方案任选
实时行情数据(如当前价格、涨跌额、成交量、换手率)的获取分为“API调用”(简单高效)和“网页爬虫”(免费无限制)两种方案,可根据需求选择。
方案一:AkShare API(新手首选,零配置)
AkShare无需注册,直接调用接口即可获取全市场实时行情,支持沪深A股、港股、美股等,数据延迟约1-3分钟(免费API正常水平)。
代码实现:获取沪深A股实时行情
import akshare as ak
import pandas as pd
def get_a股_real_time_data():
"""
获取沪深A股所有股票实时行情
返回字段:股票代码、名称、最新价、涨跌幅、成交量、成交额、换手率等
"""
# 调用AkShare接口,获取实时行情(adjust="qfq"表示前复权)
stock_real_time_df = ak.stock_zh_a_spot_em() # em表示数据来源为东方财富网
# 筛选核心字段(按需调整)
core_columns = [
"代码", "名称", "最新价", "涨跌幅", "涨跌额", "成交量",
"成交额", "换手率", "市盈率-动态", "市净率"
]
result_df = stock_real_time_df[core_columns].copy()
# 数据清洗:去除停盘股票(最新价为0或NaN)
result_df = result_df[result_df["最新价"] > 0].dropna(subset=["最新价"])
# 按涨跌幅降序排序
result_df = result_df.sort_values("涨跌幅", ascending=False)
return result_df
# 调用函数获取数据
if __name__ == "__main__":
real_time_data = get_a股_real_time_data()
print("沪深A股实时行情(前10只涨停股):")
print(real_time_data.head(10))
# 保存为CSV文件
real_time_data.to_csv("a股实时行情_2025.csv", index=False, encoding="utf-8-sig")
print("数据已保存为CSV文件")
关键说明:
接口返回约5000+只沪深A股数据,字段丰富,无需手动解析;若需获取单只股票实时数据,可通过筛选股票代码实现:
# 获取贵州茅台(600519)实时数据
maotai_data = real_time_data[real_time_data["代码"] == "600519"]
方案二:东方财富网网页爬虫(无限制,深入理解原理)
如果需要更灵活的自定义(如抓取特定板块、实时刷新频率更高),可直接爬取东方财富网的实时行情接口。东方财富网的实时行情通过AJAX加载,返回JSON格式数据,解析简单。
步骤拆解:
打开东方财富网沪深A股行情页(https://quote.eastmoney.com/center/gridlist.html#hs_a_board);按F12打开开发者工具,切换到Network→XHR,刷新页面,找到返回行情数据的接口(如);分析接口参数(如板块类型、页码、每页数量),构造请求URL。
https://82.push2.eastmoney.com/api/qt/clist/get
代码实现:东方财富网实时行情爬虫
import requests
import pandas as pd
import json
def get_eastmoney_real_time(page=1, page_size=100):
"""
爬取东方财富网沪深A股实时行情
:param page: 页码
:param page_size: 每页数据量(最大500)
:return: DataFrame格式数据
"""
# 东方财富网实时行情接口
url = "https://82.push2.eastmoney.com/api/qt/clist/get"
# 构造请求参数(分析接口得出,可调整fields获取更多字段)
params = {
"pn": page, # 页码
"pz": page_size, # 每页数量
"po": 1, # 排序方式(1=正序,0=倒序)
"np": 1, # 未知参数(固定1)
"ut": "bd1d9ddb04089700cf9c27f6f7426281", # 加密参数(固定)
"fltt": 2, # 过滤条件(2=全部A股)
"invt": 2, # 排序字段(2=涨跌幅)
"fid": "f3", # 排序字段标识(f3=涨跌幅)
"fs": "m:0 t:6,m:0 t:80,m:1 t:2,m:1 t:23", # 板块筛选(沪深A股)
"fields": "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18", # 返回字段
"_": 1740000000000 # 时间戳(可动态生成)
}
# 伪装请求头,避免被识别为爬虫
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Referer": "https://quote.eastmoney.com/",
"Accept": "application/json, text/javascript, */*; q=0.01"
}
try:
response = requests.get(url, params=params, headers=headers, timeout=10)
response.encoding = "utf-8"
# 解析JSON数据
data = json.loads(response.text)
if data["data"] is None:
print("暂无数据")
return pd.DataFrame()
# 提取股票列表
stock_list = data["data"]["diff"]
# 字段映射(接口返回的是简写字段,映射为中文)
field_map = {
"f12": "代码", "f14": "名称", "f2": "最新价", "f3": "涨跌幅",
"f4": "涨跌额", "f5": "成交量(手)", "f6": "成交额(万元)",
"f7": "换手率(%)", "f8": "市盈率(动态)", "f9": "市净率",
"f10": "量比", "f15": "最高", "f16": "最低", "f17": "今开", "f18": "昨收"
}
# 转换为DataFrame并映射字段
df = pd.DataFrame(stock_list)
df = df.rename(columns=field_map)
df = df[list(field_map.values())] # 调整字段顺序
return df
except Exception as e:
print(f"爬取失败:{e}")
return pd.DataFrame()
# 调用函数,获取前3页数据(共300只股票)
if __name__ == "__main__":
all_data = []
for page in range(1, 4):
page_data = get_eastmoney_real_time(page=page, page_size=100)
all_data.append(page_data)
print(f"已获取第{page}页数据,共{len(page_data)}只股票")
# 合并数据
result_df = pd.concat(all_data, ignore_index=True)
print(f"
总数据量:{len(result_df)}只股票")
print(result_df.head())
# 保存为CSV
result_df.to_csv("东方财富网实时行情.csv", index=False, encoding="utf-8-sig")
反爬应对:
必须携带和
User-Agent,否则会返回403;避免高频请求,建议每5-10秒请求一次,可添加
Referer控制频率;若需大量爬取,可使用IP池(参考之前的IP池实现)。
time.sleep(5)
三、历史K线数据获取:日线/周线/月线全覆盖
历史K线数据(开盘价、最高价、最低价、收盘价、成交量)是量化分析的核心,支持日线、周线、月线、分钟线等多种周期,同样提供API和爬虫两种方案。
方案一:Tushare API(数据质量高,推荐)
Tushare的历史K线数据接口稳定,字段规范,支持复权处理(前复权、后复权、不复权),适合量化回测。需先注册账号(https://tushare.pro/),获取token(个人中心→接口token)。
代码实现:获取个股历史日线数据
import tushare as ts
import pandas as pd
import matplotlib.pyplot as plt
import mplfinance as mpf
# 设置Tushare token(替换为自己的token)
ts.set_token("your_tushare_token")
pro = ts.pro_api()
def get_stock_hist_k_data(stock_code, start_date, end_date, freq="D"):
"""
获取个股历史K线数据
:param stock_code: 股票代码(如600519.SH代表贵州茅台)
:param start_date: 起始日期(格式:YYYYMMDD)
:param end_date: 结束日期(格式:YYYYMMDD)
:param freq: 周期(D=日线,W=周线,M=月线,1MIN=1分钟线)
:return: 格式化后的DataFrame
"""
try:
# 调用Tushare接口
df = pro.daily(
ts_code=stock_code,
start_date=start_date,
end_date=end_date,
adj="qfq" # qfq=前复权,hfq=后复权,None=不复权
)
# 数据处理:转换日期格式,调整字段顺序
df["trade_date"] = pd.to_datetime(df["trade_date"], format="%Y%m%d")
df = df.sort_values("trade_date") # 按日期升序排序
# 重命名字段(便于后续可视化)
df = df.rename(columns={
"trade_date": "date",
"open": "开盘价",
"high": "最高价",
"low": "最低价",
"close": "收盘价",
"vol": "成交量(手)",
"amount": "成交额(万元)"
})
# 设置日期为索引(mplfinance要求)
df = df.set_index("date")
return df
except Exception as e:
print(f"获取K线数据失败:{e}")
return pd.DataFrame()
# 调用函数:获取贵州茅台(600519.SH)2024年1月1日至2024年12月31日的日线数据
if __name__ == "__main__":
stock_data = get_stock_hist_k_data(
stock_code="600519.SH",
start_date="20240101",
end_date="20241231",
freq="D"
)
print("贵州茅台2024年日线数据:")
print(stock_data.head())
# 保存为CSV
stock_data.to_csv("贵州茅台2024年日线数据.csv", encoding="utf-8-sig")
# 绘制K线图(后续可视化部分详细说明)
mpf.plot(
stock_data,
type="candle", # 蜡烛图(K线图)
mav=(5, 10, 20), # 5日、10日、20日均线
volume=True, # 显示成交量
title="贵州茅台2024年日线K线图",
ylabel="价格(元)",
ylabel_lower="成交量(手)",
figratio=(15, 8), # 图表比例
# 图表风格
)
关键说明:
股票代码格式:沪市股票后缀(如600519.SH),深市股票后缀
.SH(如000858.SZ);周期参数:
.SZ获取周线,
freq="W"获取月线,
freq="M"获取1分钟线(需足够积分);复权处理:
freq="1MIN"前复权(推荐,便于对比不同时期价格),
adj="qfq"后复权。
adj="hfq"
方案二:东方财富网K线爬虫(免费无积分限制)
若不想注册Tushare,可爬取东方财富网个股K线接口,支持日线、周线、月线,数据格式清晰。
代码实现:爬取个股历史日线数据
import requests
import pandas as pd
import json
from datetime import datetime
def get_eastmoney_hist_k(stock_code, start_date, end_date, freq="101"):
"""
爬取东方财富网个股历史K线数据
:param stock_code: 股票代码(如600519)
:param start_date: 起始日期(格式:YYYY-MM-DD)
:param end_date: 结束日期(格式:YYYY-MM-DD)
:param freq: 周期(101=日线,102=周线,103=月线)
:return: DataFrame格式数据
"""
# 转换日期为时间戳(东方财富网接口要求)
def date_to_timestamp(date_str):
dt = datetime.strptime(date_str, "%Y-%m-%d")
return int(dt.timestamp() * 1000)
start_ts = date_to_timestamp(start_date)
end_ts = date_to_timestamp(end_date)
# 构造股票代码(东方财富网格式:沪市sh600519,深市sz000858)
if stock_code.startswith("6"):
em_code = f"sh{stock_code}"
else:
em_code = f"sz{stock_code}"
# 东方财富网K线接口
url = f"https://push2his.eastmoney.com/api/qt/stock/kline/get"
params = {
"secid": em_code, # 股票代码(东方财富格式)
"fields1": "f1,f2,f3,f4,f5,f6",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61",
"klt": freq, # 周期(101=日线,102=周线,103=月线)
"fqt": 1, # 复权类型(1=前复权,2=后复权,0=不复权)
"beg": start_ts, # 起始时间戳(毫秒)
"end": end_ts, # 结束时间戳(毫秒)
"_": int(datetime.now().timestamp() * 1000)
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Referer": f"https://quote.eastmoney.com/{em_code}.html"
}
try:
response = requests.get(url, params=params, headers=headers, timeout=15)
data = json.loads(response.text)
if data["data"] is None:
print("暂无数据")
return pd.DataFrame()
# 提取K线数据(data字段是字符串,按逗号分隔)
kline_str = data["data"]["klines"]
kline_list = [line.split(",") for line in kline_str]
# 字段定义(按东方财富网返回顺序)
columns = [
"日期", "开盘价", "收盘价", "最高价", "最低价",
"成交量(手)", "成交额(万元)", "换手率(%)",
"振幅(%)", "涨跌幅(%)", "涨跌额(元)"
]
# 转换为DataFrame
df = pd.DataFrame(kline_list, columns=columns)
# 数据类型转换(字符串转数值)
numeric_columns = columns[1:] # 除日期外的字段转为数值
for col in numeric_columns:
df[col] = pd.to_numeric(df[col], errors="coerce")
# 日期格式转换
df["日期"] = pd.to_datetime(df["日期"])
# 设置日期为索引
df = df.set_index("日期").sort_index()
return df
except Exception as e:
print(f"爬取K线数据失败:{e}")
return pd.DataFrame()
# 调用函数:获取贵州茅台(600519)2024年日线数据
if __name__ == "__main__":
k_data = get_eastmoney_hist_k(
stock_code="600519",
start_date="2024-01-01",
end_date="2024-12-31",
freq="101" # 101=日线
)
print("贵州茅台2024年日线数据(东方财富网):")
print(k_data.head())
# 保存为CSV
k_data.to_csv("贵州茅台2024年日线数据_东方财富.csv", encoding="utf-8-sig")
# 绘制K线图
mpf.plot(
k_data,
type="candle",
mav=(5, 10, 20),
volume=True,
title="贵州茅台2024年日线K线图(东方财富网数据)",
ylabel="价格(元)",
ylabel_lower="成交量(手)",
figratio=(15, 8),
)
四、数据存储:CSV vs 数据库(长期使用推荐数据库)
4.1 保存为CSV文件(简单快捷)
前面的案例中已展示如何保存为CSV文件,适合临时使用或小量数据存储:
# DataFrame保存为CSV
df.to_csv("股票数据.csv", index=False, encoding="utf-8-sig")
:解决中文乱码问题;
encoding="utf-8-sig":不保存索引列(若需保存日期索引,可去掉该参数)。
index=False
4.2 存入SQLite数据库(长期存储,便于查询)
SQLite无需额外安装数据库服务,文件型数据库,适合个人或小型项目使用:
import sqlite3
from sqlite3 import Error
def save_to_sqlite(df, db_name="stock_data.db", table_name="stock_hist_k"):
"""
将股票数据存入SQLite数据库
:param df: 待存储的DataFrame
:param db_name: 数据库文件名
:param table_name: 表名
"""
try:
# 连接数据库(不存在则创建)
conn = sqlite3.connect(db_name)
cursor = conn.cursor()
# 创建表(若不存在)
create_table_sql = f"""
CREATE TABLE IF NOT EXISTS {table_name} (
日期 TEXT PRIMARY KEY,
开盘价 REAL,
收盘价 REAL,
最高价 REAL,
最低价 REAL,
成交量 INTEGER,
成交额 REAL,
换手率 REAL,
振幅 REAL,
涨跌幅 REAL,
涨跌额 REAL
)
"""
cursor.execute(create_table_sql)
# 插入数据(若已存在则更新)
df.to_sql(
name=table_name,
con=conn,
if_exists="replace", # replace=替换表,append=追加数据
index=True,
index_label="日期"
)
conn.commit()
print(f"数据已成功存入SQLite数据库:{db_name},表名:{table_name}")
except Error as e:
print(f"存入数据库失败:{e}")
finally:
if conn:
conn.close()
# 调用函数:将K线数据存入SQLite
if __name__ == "__main__":
k_data = get_eastmoney_hist_k("600519", "2024-01-01", "2024-12-31")
save_to_sqlite(k_data, db_name="stock_data.db", table_name="maotai_hist_k")
4.3 从数据库查询数据
def query_from_sqlite(db_name="stock_data.db", table_name="maotai_hist_k", date_range=None):
"""
从SQLite查询股票数据
:param date_range: 日期范围(如("2024-06-01", "2024-06-30"))
:return: DataFrame
"""
try:
conn = sqlite3.connect(db_name)
if date_range:
# 查询指定日期范围的数据
sql = f"""
SELECT * FROM {table_name}
WHERE 日期 BETWEEN '{date_range[0]}' AND '{date_range[1]}'
ORDER BY 日期
"""
else:
# 查询所有数据
sql = f"SELECT * FROM {table_name} ORDER BY 日期"
df = pd.read_sql(sql, con=conn, index_col="日期")
conn.close()
return df
except Error as e:
print(f"查询数据库失败:{e}")
return pd.DataFrame()
# 查询2024年6月的贵州茅台数据
query_df = query_from_sqlite(date_range=("2024-06-01", "2024-06-30"))
print("2024年6月贵州茅台数据:")
print(query_df.head())
五、反爬应对策略:股票网站专属解决方案
股票类网站(如东方财富网、同花顺)的反爬机制相对严格,主要针对高频请求和异常请求特征,以下是实战验证有效的应对方法:
5.1 基础伪装:请求头优化
携带完整的请求头,包括、
User-Agent、
Referer等,避免单一请求头;随机切换
Accept,模拟不同浏览器:
User-Agent
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/125.0"
]
headers["User-Agent"] = random.choice(USER_AGENTS)
5.2 频率控制:避免高频请求
单IP请求间隔控制在3-5秒以上,尤其是东方财富网,高频请求会直接封禁IP;批量爬取时,使用设置随机延迟。
time.sleep(random.uniform(3, 5))
5.3 IP池:突破IP封禁限制
若需大量爬取(如全市场所有股票的历史数据),必须使用IP池,推荐混合使用付费代理和动态拨号IP;代理池需支持高匿名性,避免透明代理泄露真实IP(参考之前的IP池实现)。
5.4 Cookie处理:模拟登录状态
部分网站的历史数据接口需要登录后才能获取,可通过保存登录Cookie:
requests.Session()
session = requests.Session()
# 先登录,保存Cookie
login_data = {"username": "your_username", "password": "your_password"}
session.post(login_url, data=login_data)
# 后续请求使用session,自动携带Cookie
response = session.get(url, params=params, headers=headers)
六、实战案例:整合实时+历史数据,实现股票分析小工具
需求:
获取贵州茅台实时行情;获取近1年日线数据;计算近30日涨跌幅;绘制K线图并标注实时价格;保存数据到SQLite数据库。
完整代码:
import akshare as ak
import tushare as ts
import pandas as pd
import mplfinance as mpf
import sqlite3
from datetime import datetime, timedelta
# Tushare配置
ts.set_token("your_tushare_token")
pro = ts.pro_api()
def get_real_time_price(stock_code):
"""获取单只股票实时价格"""
real_time_df = ak.stock_zh_a_spot_em()
stock_data = real_time_df[real_time_df["代码"] == stock_code]
if not stock_data.empty:
return {
"名称": stock_data["名称"].iloc[0],
"最新价": stock_data["最新价"].iloc[0],
"涨跌幅": stock_data["涨跌幅"].iloc[0],
"更新时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
else:
return None
def get_recent_year_k_data(stock_code):
"""获取近1年日线数据"""
end_date = datetime.now().strftime("%Y%m%d")
start_date = (datetime.now() - timedelta(days=365)).strftime("%Y%m%d")
df = pro.daily(
ts_code=stock_code,
start_date=start_date,
end_date=end_date,
adj="qfq"
)
df["trade_date"] = pd.to_datetime(df["trade_date"], format="%Y%m%d")
df = df.rename(columns={
"trade_date": "日期", "open": "开盘价", "high": "最高价",
"low": "最低价", "close": "收盘价", "vol": "成交量"
})
df = df.set_index("日期").sort_index()
return df
def calculate_30d_change(df):
"""计算近30日涨跌幅"""
if len(df) < 30:
return None
recent_30d = df.tail(30)
start_price = recent_30d["收盘价"].iloc[0]
end_price = recent_30d["收盘价"].iloc[-1]
change_rate = (end_price - start_price) / start_price * 100
return round(change_rate, 2)
def save_to_sqlite(df, real_time_data, db_name="stock_analysis.db"):
"""保存数据到SQLite"""
conn = sqlite3.connect(db_name)
# 保存历史K线数据
df.to_sql("hist_k_data", con=conn, if_exists="replace", index=True)
# 保存实时数据
real_time_df = pd.DataFrame([real_time_data])
real_time_df.to_sql("real_time_data", con=conn, if_exists="replace", index=False)
conn.close()
print("数据已保存到数据库")
def plot_k_line_with_real_time(df, real_time_data):
"""绘制K线图并标注实时价格"""
# 准备实时价格标注数据
last_date = df.index[-1]
real_price = real_time_data["最新价"]
# 绘制K线图
apds = [
mpf.make_addplot([real_price] * len(df), color="red", linestyle="--", label=f"实时价格:{real_price}元"),
]
mpf.plot(
df,
type="candle",
mav=(5, 10, 20),
volume=True,
addplot=apds,
title=f"{real_time_data['名称']}近1年K线图(实时价格标注)",
ylabel="价格(元)",
ylabel_lower="成交量",
figratio=(15, 8),
,
warn_too_much_data=1000
)
if __name__ == "__main__":
stock_code = "600519.SH" # 贵州茅台
print("="*50)
print("开始获取股票数据...")
# 1. 获取实时数据
real_time_data = get_real_time_price("600519")
if not real_time_data:
print("获取实时数据失败")
exit()
print(f"实时行情:{real_time_data}")
# 2. 获取近1年K线数据
k_data = get_recent_year_k_data(stock_code)
print(f"
近1年K线数据量:{len(k_data)}条")
print(k_data.tail())
# 3. 计算近30日涨跌幅
change_30d = calculate_30d_change(k_data)
print(f"
近30日涨跌幅:{change_30d}%")
# 4. 保存数据到数据库
save_to_sqlite(k_data, real_time_data)
# 5. 绘制K线图
plot_k_line_with_real_time(k_data, real_time_data)
print("="*50)
七、注意事项与法律风险
数据用途限制:本文提供的方法仅用于个人学习和研究,不得用于商业用途或非法获取利益;遵守网站规则:爬取前查看目标网站的协议,不得过度爬取影响网站正常运行;反爬合规:避免使用恶意爬虫手段(如高频请求、伪造身份),否则可能面临IP封禁、法律责任;数据时效性:免费API和网页爬虫的实时数据存在延迟,不适合用于实盘交易决策;接口稳定性:网页爬虫依赖网站接口结构,若网站更新接口,代码可能需要调整。
robots.txt
八、总结与扩展方向
本文覆盖了股票数据获取的核心场景:实时行情(API+爬虫)、历史K线(多周期)、数据存储(CSV+SQLite)、可视化(K线图)、反爬应对,代码可直接复用。后续可扩展的方向:
多股票批量获取:循环遍历股票代码列表,批量获取全市场股票数据;分钟级数据抓取:通过API或爬虫获取1分钟/5分钟线数据,实现高频交易分析;量化策略回测:结合历史K线数据,实现均线策略、MACD策略等回测;实时监控告警:定时抓取实时数据,当价格突破阈值时发送邮件/短信告警;多数据源对比:整合多个数据源(如Tushare、AkShare、东方财富网),交叉验证数据准确性。
如果在实战中遇到接口变化、反爬升级、数据解析等问题,欢迎留言交流!

















暂无评论内容