直接上代码
import requests, random, re, json
from datetime import datetime, date
from chinese_calendar import is_workday
from pydantic import BaseModel
class StockInfo(BaseModel):
stock_code: str
stock_name: str
date: date
open: float
high: float
low: float
close: float
yid: float
volumn: float
price: float
PE: float
class Error(BaseModel):
Error: str
class SSEQuery(object):
def __init__(self):
self.url = 'http://query.sse.com.cn/commonQuery.do'
self.headers = {
'Host': 'query.sse.com.cn',
'Referer': 'http://www.sse.com.cn/',
}
def get_jsonp(self):
return f'jsonpCallback{int(random.random()*(10000000+1))}'
def get_timestamp(self):
return str(int(datetime.timestamp(datetime.now()) * 1000))
def start_request(self, stock_code, date):
jsonp = self.get_jsonp()
timestamp = self.get_timestamp()
url = self.url
headers = self.headers
data = {
'jsonCallBack': jsonp,
'sqlId': 'COMMON_SSE_CP_GPJCTPZ_GPLB_CJGK_MRGK_C',
'SEC_CODE': stock_code,
'TX_DATE': date,
'TX_DATE_MON': '',
'TX_DATE_YEAR': '',
'_': timestamp,
}
return requests.post(url, data=data, headers=headers)
def parse_jsonp(self, r):
return json.loads(re.search(r'jsonpCallback\d+\((.*?)\)', r.text).group(1))['result'][0]
def check_date(self, date):
if not is_workday(datetime.date(datetime.strptime(date, '%Y-%m-%d'))):
return False
if datetime.date(datetime.strptime(date, '%Y-%m-%d')).weekday()>4:
return False
return date
def format_dict(self, data):
return {
'stock_code': data['SEC_CODE'],
'stock_name': data['SEC_NAME'],
'open': data['OPEN_PRICE'],
'high': data['HIGH_PRICE'],
'low': data['LOW_PRICE'],
'close': data['CLOSE_PRICE'],
'yid': data['CHANGE_RATE'],
'volumn': data['TRADE_VOL'],
'price': data['TRADE_AMT'],
'PE': data['PE_RATE'],
}
def query(self, stock_code, date):
date = self.check_date(date)
if not date:
return Error(**{'Error':'非交易日!'})
r = self.start_request(stock_code, date)
data = self.parse_jsonp(r)
data = self.format_dict(data)
data.update({'date': date})
return StockInfo(**data)
class SZSEQuery(object):
def __init__(self):
self.url = 'http://www.szse.cn/api/report/ShowReport/data'
def check_date(self, date):
if not is_workday(datetime.date(datetime.strptime(date, '%Y-%m-%d'))):
return False
if datetime.date(datetime.strptime(date, '%Y-%m-%d')).weekday()>4:
return False
return date
def start_request(self, stock_code, date):
data = {
'SHOWTYPE': 'JSON',
'CATALOGID': '1815_stock',
'TABKEY': 'tab1',
'txtDMorJC': str(stock_code),
'txtBeginDate': date,
'txtEndDate': date,
'radioClass': '00%2C20%2C30%2CC6%2CC7%2CGE%2C14',
'txtSite': 'all',
'random': random.random(),
}
return requests.get(self.url, data)
def format_dict(self, data):
return {
'stock_code': data['zqdm'],
'stock_name': data['zqjc'].replace(' ',''),
'open': data['ks'],
'high': data['zg'],
'low': data['zd'],
'close': data['ss'],
'yid': data['sdf'],
'volumn': data['cjgs'].replace(',' ,''),
'price': data['cjje'].replace(',' ,''),
'PE': data['syl1'],
}
def query(self, stock_code, date):
date = self.check_date(date)
if not date:
return Error(**{'Error':'非交易日!'})
r = self.start_request(stock_code, date)
data = self.format_dict(r.json()[0]['data'][0])
data.update({'date': date})
return StockInfo(**data)
def query(stock_code, date):
try:
if stock_code[:1] in ['0', ['3']]:
szsequery = SZSEQuery()
return szsequery.query(stock_code, date)
else:
ssequery = SSEQuery()
return ssequery.query(stock_code, date)
except:
try:
szsequery = SZSEQuery()
return szsequery.query(stock_code, date)
except:
return Error(**{"Error": "查询失败!"})
最先想搞一个股票数据库来着,所以准备开始爬上交所的数据,被一个jsonpcallback搞昏了头,弄了一个多小时,结果发现是真的坑,后来就不高兴全爬下来当数据库了,直接写一个从上交所/深交所查单日行情的小工具算了。
数据来源
上交所:http://www.sse.com.cn/assortment/stock/list/info/company/index.shtml?COMPANY_CODE=600008
深交所:https://www.szse.cn/market/trend/index.html?code=000002
返回格式
其实是一个pydantic的BaseModel,你可以用.dict()/.json()方法把它变成列表/JSON。
stock_code: str # 股票代码 stock_name: str # 股票名称 date: date # 日期 open: float # 开盘价 high: float # 最高价 low: float # 最低价 close: float # 收盘价 yid: float # 当日盈亏率 volumn: float # 成交股数(万) price: float # 成交金额(万) PE: float # 市盈率
使用方法
直接query(stock_code, date)
或者另起一个文件,比如main.py,然后
from tickerlookup import query # 上交所 600008 首创环保 stock_code = '600008' date = '2023-01-04' print(query(stock_code, date).dict()) # 深交所 000002 万科A stock_code = '000002' date = '2023-01-04' print(query(stock_code, date).dict())
运行结果:
{'stock_code': '600008', 'stock_name': '首创环保', 'date': datetime.date(2023, 1, 4),
'open': 2.89, 'high': 2.91, 'low': 2.87, 'close': 2.89, 'yid': 0.34722,
'volumn': 4234.94, 'price': 12255.84, 'PE': 9.27414}
{'stock_code': '000002', 'stock_name': '万科A', 'date': datetime.date(2023, 1, 4),
'open': 18.25, 'high': 19.28, 'low': 18.07, 'close': 19.07, 'yid': 4.61,
'volumn': 10871.46, 'price': 206031.74, 'PE': 9.84}



Comments | NOTHING