

昨天写了一篇关于同花顺板块的文章,有反馈开盘啦的概念板块比同花顺好。 虽然我之前基于开盘啦抓取过概念板块。 但不是根据每日强度来的,抓取的页面不同,那对应的接口肯定不一样。那这里简单写一写,就当每日技术文章总结了。
这个代码其实是星球同学写的初稿,他反馈接口出现时灵时不灵的情况,我就在基础上做了下细微优化,增加了一些user-agent等特征。毕竟抓取接口我们需要考虑user-agent, content-type等header设置,不然会被服务器识别成爬虫,不会返回对应的数据。
题外话:
这个功能和 开盘啦APP的功能本质上没什么区别, 我们其实可以换个思路,监听每日板块强度变化, 找出板块领涨个股, 然后把变化数据推送给钉钉或企业微信,助力抓龙头。
比如昨天脑机接口很强, 我们是不是就可以找机会买板块的个股, 虽然我买的狄耐克 表现一般, 但也有8个点的小肉, 没涨停可惜了。
鉴于东方财富之前akshare用的人多了后续官方多了限制,这里开盘啦我就不公开提供完整代码了, 提供一下代码思路,免得又闹幺蛾子。 仅供学习研究,不要用于商业用途。
伪代码提供如下, 代码里 URL和链接我脱敏成了XXX,你完全可以借助fiddler或charles自行监控 完成完整代码编写。 其实很简单
import streamlit as st
import requests
import datetime
import pandas as pd
import json
def get_sector_data(date, k):
# 基本URL
url1 = "https://XXX"
url2 = "https://XXX"
# 请求头配置(完全匹配API要求)
headers = {
"Host": "XXXX" if k == 1 else "XXX",
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"Connection": "keep-alive",
"Accept": "*/*",
"User-Agent": "lhb/5.17.9 (XXXX; build:0; iOS 16.6.0) Alamofire/4.9.1",
"Accept-Language": "zh-Hans-CN;q=1.0",
"Accept-Encoding": "gzip;q=1.0, compress;q=0.5"
}
# 构建请求体参数(完全匹配API格式)
params = {
"Date": date if k == 1 else datetime.date.today().strftime("%Y-%m-%d"),
"Index": "0",
"Order": "1",
"PhoneOSNew": "2",
"Type": "1",
"VerSion": "5.17.0.9",
"ZSType": "7",
"a": "XXXXXX",
"apiv": "w38",
"c": "XXXXX",
"st": "20"
}
url = url1 if k == 0 else url2
print(f"请求URL: {url}")
print(f"请求参数: {params}")
try:
# 发送POST请求(参数放在请求体中)
response = requests.post(
url,
headers=headers,
data=params
)
if response.status_code == 200:
data = response.json()
if "list" in data and data["list"]:
sector_list = []
for item in data["list"]:
if len(item) >= 4:
sector_list.append({
"代码": item[0],
"名称": item[1],
"强度": item[2],
"涨幅%": item[3]
})
return sector_list
else:
st.error("返回数据缺少'list'字段或为空")
else:
st.error(f"API返回错误状态码: {response.status_code}")
except Exception as e:
st.error(f"获取数据时出错:{str(e)}")
return []
def get_stock_data(sector_code, date, k):
# 基本URL
url1 = "XXXXX"
url2 = "XXXXX"
# 请求头配置
headers = {
"Host": "XXXX" if k == 1 else "XXXX",
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"Connection": "keep-alive",
"Accept": "*/*",
"User-Agent": "lhb/5.17.9 (XXXX; build:0; iOS 16.6.0) Alamofire/4.9.1",
"Accept-Language": "zh-Hans-CN;q=1.0",
"Accept-Encoding": "gzip;q=1.0, compress;q=0.5"
}
# 构建请求体参数
params = {
"PlateID": sector_code,
"Date": date if k == 1 else datetime.date.today().strftime("%Y-%m-%d"),
"Index": "0",
"Order": "1",
"PhoneOSNew": "2",
"Type": "6",
"VerSion": "5.17.0.9",
"a": "XXXXX",
"apiv": "w38",
"c": "XXXXX",
"st": "20"
}
url = url1 if k == 0 else url2
try:
# 发送POST请求(参数放在请求体中)
response = requests.post(
url,
headers=headers,
data=params # 关键修改:使用data参数
)
if response.status_code == 200:
data = response.json()
if "list" in data and data["list"]:
stock_list = []
for item in data["list"]:
if len(item) >= 24: # 确保有足够字段
stock_list.append({
"代码": item[0],
"名称": item[1],
"涨幅%": item[6],
"连板": item[23],
"板块": item[4]
})
return stock_list
else:
st.error("个股返回数据缺少'list'字段或为空")
except Exception as e:
st.error(f"获取个股数据时出错:{str(e)}")
return []
def app():
st.title("精选板块")
today = datetime.date.today()
formatted_today = today.strftime("%Y-%m-%d")
date_range = [today - datetime.timedelta(days=i) for i in range(30)]
formatted_date_range = [date.strftime("%Y-%m-%d") for date in date_range]
selected_date = st.selectbox("选择日期", formatted_date_range, index=0)
# 确定数据源类型(实时/历史)
k = 0 if selected_date == formatted_today else 1
# 获取板块数据
sector_data = get_sector_data(selected_date, k)
if sector_data:
df = pd.DataFrame(sector_data)
st.dataframe(df)
# 添加个股查询功能
selected_sector_code = st.selectbox("选择板块代码查看个股信息", df["代码"].tolist())
if selected_sector_code:
stock_data = get_stock_data(selected_sector_code, selected_date, k)
if stock_data:
stock_df = pd.DataFrame(stock_data)
st.dataframe(stock_df)
else:
st.warning("未获取到个股数据,请检查参数或网络连接")
else:
st.error("获取板块数据失败,请稍后重试")
if __name__ == "__main__":
app()