代码拉取完成,页面将自动刷新
import requests as rq
from html.parser import HTMLParser
FILE_SECIDS = 'Cache/secids.dat' # secids.dat 文件路径
SECIDS = ['0.', '1.'] # 可能的secid
FILE_TEMPPIC = 'Cache/tempStockTrend.png'
FILE_TRYALLERROR = 'ErrorLog/TryAll.log'
FILE_RESPONSEERROR = 'ErrorLog/Response.log'
def tryallsecidlog(text):
"""
尝试所有secid都未成功的错误日志
:return:
"""
with open(FILE_TRYALLERROR, 'a') as file:
file.write(text)
def responselog(url, params, response):
"""
记录返回数据错误
:param url: 地址
:param params: 请求参数
:param response: 返回值
:return:
"""
log = 'url: %s\nParams: %s\nResponse: %s\n\n' % (url, params, response)
with open(FILE_RESPONSEERROR, 'a') as file:
file.write(log)
def read_secids():
"""
获取本地存储secids
:return:
【dict】 - {'300750': '0.'}
"""
import os
secids_dict = {} # 创建新的空的secids字典
# 打开secid缓存文件
if not os.path.isfile(FILE_SECIDS):
print('secids.dat文件不存在!!!')
pass
else:
# 文件存在,直接读文件,并转换为字典
with open(FILE_SECIDS, 'r') as file:
file_content = file.read()
if not file_content:
# 文件内容为空
print('secids.dat内容为空!!!')
pass
else:
# 尝试转换为字典,如果报错内容被损坏
try:
secids_dict = eval(file_content)
except SyntaxError:
print('secids.dat 内容损坏!!!')
pass
# 校验secid是否符合规则
for key in secids_dict.keys():
if not secids_dict[key] in SECIDS:
print(f'{key} secid不符合规则!!!')
# 给个默认secid
secids_dict[key] = '0.'
return secids_dict
def write_secids(secids: dict):
"""
将成功的secids存储到缓存中
:param secids: 成功的secids字典
:return:
"""
# 存储成功的secids
with open(FILE_SECIDS, 'w') as file:
file.write(str(secids))
def requests_get(url, headers=None, params=None, timeout=30, often=False):
"""
requests get请求
:param url: 访问地址
:param headers: 请求头
:param params: 请求参数
:param timeout: 请求超时时间 单位 s
:param often: 是否开启频繁访问,如果为True不会延时直接访问,
:return:
<rq对象>
【'Time out'】 请求超时
【'Network error'】 网络连接错误
"""
from time import sleep
from random import randint
try:
# 间隔访问,防止频繁访问被拉黑
if not often:
sleep(randint(200, 1000) / 1000)
return rq.get(url, headers=headers, params=params, timeout=timeout)
except rq.exceptions.ConnectTimeout: # 请求超时
return 'Time out'
except rq.exceptions.ConnectionError: # 网络连接错误
return 'Network error'
def connect_dfcf(often=False):
"""
https://www.eastmoney.com/ # 东方财富官网
检查连接是否正常,获取时间
:param often: 是否开启无延时访问
:return:
【'Time out'】 请求超时
【'Network error'】 网络连接错误
【int】 - 1626245924 时间戳,秒级
"""
import time
# 访问东方财富网
response = requests_get('https://www.eastmoney.com/', timeout=8, often=often)
if isinstance(response, str):
# 访问出错!!!
return response
date = response.headers['date']
# print(f'响应头时间:{date}')
ltime = time.strptime(date[5:25], "%d %b %Y %H:%M:%S")
time_stamp = time.mktime(ltime) + 8 * 60 * 60 # 将GMT时间转换成北京时间
# print(time_stamp)
return int(time_stamp)
def try_get(code, url, sectype='secid', headers=None, params=None):
"""
尝试secid
:param code: 股票代码
:param sectype: 参数形式,因为获股票价格和个股信息secid参数形式不一样
:param url: 访问地址
:param headers: 请求头
:param params: 请求参数
:return:
【'Time out'】 请求超时
【'Network error'】 网络连接错误
【list】 - 尝试成功。[0] - 成功的secid,[1] - 成功的数据
"""
for secid_ in SECIDS:
secid = secid_ + str(code)
print(f'可能的secid: {secid}')
# 尝试访问
params[sectype] = secid
response = requests_get(url, headers, params)
if isinstance(response, str):
# 返回如果是str,说明访问出错
return response
# 判断访问是否有数据
jsondata = response.json()
print(f'返回结果(json):{jsondata}')
if jsondata['data']:
# 已获取到数据
return secid_, jsondata
# 如果所有可能的secid全部尝试,记录股票代码信息
print(f'{code} 尝试所有前缀({SECIDS})失败:')
return None, None
def get_newestprice(codes):
"""
获取股票最新价格 (带最新价格日期)
:param codes: 股票代码列表
:return:
【dict】 - {'300750': [日期, 最新价格], ......}
【Time out】 - 超时
【Network error】 - 网络错误
"""
rslt = {} # 存储成功获取最新价格的数据
url = 'https://push2.eastmoney.com/api/qt/stock/trends2/get?'
params = {
'fields1': 'f1', # 可选值f1 - fn。这里只用到 f2(),f12
'fields2': 'f51,f53', # f51时间;f52收盘价
}
# 获取本地secids
secids = read_secids()
for code in codes:
print(f'正在获取 {code} 的最新价格...')
data = None # 爬取到的数据
# 判断本地是否存储了secid
try:
secid_ = secids[str(code)]
secid = secid_ + str(code)
# 访问最新价格接口
params['secid'] = secid # 股票的secid
response = requests_get(url, params=params)
if isinstance(response, str):
# 如果返回的是str,说明访问有误
return response
# 无访问错误
jsondata = response.json()
# 判断返回是否有数据
if jsondata['data']:
data = jsondata['data']
except KeyError:
print(f'本地未存储 {code} 的 secid 前缀')
pass
# 如果data为空, 尝试所有可能的secid
if not data:
secid, jsondata = try_get(code, url, params=params)
if not secid:
# 所有可能的secid尝试失败,可能股票代码错误,或其他
tryallsecidlog(f'get_newestprice({code})\n')
print(f'跳过 {code}')
continue
else:
# 存储或改变secid
secids[str(code)] = secid
data = jsondata['data']
# 处理数据
newestPrice, newestDate = data['trends'][-1].split(',')
print(f'{code} 最新价格:{newestPrice,newestDate}')
rslt[str(code)] = newestPrice, newestDate
# 存储成功的secid
write_secids(secids)
return rslt
def get_stockinfo(code):
"""
获取个股信息
:param code: 股票代码
:return:
【dict】 - {
"f2": 最新价
"f3": 浮率
"f4": 浮动价格
"f5": 成交量(手)
"f6": 成交额(元)
"f8": 换手率
"f9": 动态市盈率
"f10": 量比
"f12": 股票代码
"f14": 股票简称
"f15": 最高
"f16": 最底
"f17": 今开
"f18": 昨收
"f20": 总市值(元)
"f21": 流通市值(元)
"f23": 市净
}
【'TryAll error'】 - 所有secid尝试失败
【'Time out'】 - 超时
【'Network error'】 - 网络错误
"""
url = 'https://push2.eastmoney.com/api/qt/ulist.np/get?'
fields_par = [
"f2", # 最新价
"f3", # 浮率
"f4", # 浮动价格
"f5", # 成交量(手)
"f6", # 成交额(元)
"f8", # 换手率
"f9", # 动态市盈率
"f10", # 量比
"f12", # 股票代码
"f14", # 股票简称
"f15", # 最高
"f16", # 最底
"f17", # 今开
"f18", # 昨收
"f20", # 总市值(元)
"f21", # 流通市值(元)
"f23" # 市净
]
fields = ''
for par in fields_par:
fields += par + ','
fields = fields[:-1]
params = {
'fltt': 2, # 2位小数
'invt': 2, # Unknow
'fields': fields # 可选值f1 - fn。暂只了解到 f30
}
# 获取本地secids
secids = read_secids()
data = None # 爬取到的数据
# 判断本地是否存储了secid
try:
secid_ = secids[str(code)]
secid = secid_ + str(code)
# 访问接口
params['secids'] = secid # 股票的secid
response = requests_get(url, params=params)
if isinstance(response, str):
# 如果返回的是str,说明访问有误
return response
# 无访问错误
jsondata = response.json()
# 判断返回是否有数据
if jsondata['data']:
data = jsondata['data']
except KeyError:
print(f'本地未存储 {code} 的 secid 前缀')
pass
# 如果data为空, 尝试所有可能的secid
if not data:
tryReponse = try_get(code, url, sectype='secids', params=params)
if isinstance(tryReponse, str):
# 如果返回的是字符串,访问网址出错
return tryReponse
secid, jsondata = tryReponse
if not secid:
# 所有可能的secid尝试失败,可能股票代码错误,或其他
tryallsecidlog(f'get_stockinfo({code})\n')
return 'TryAll error'
else:
# 存储或改变secid
secids[str(code)] = secid
data = jsondata['data']
# 存储成功的secid
write_secids(secids)
return data['diff'][0]
def download_stocktrend(code):
"""
下载个股走势图
:param code: 股票代码
:return:
【True】 - 下载完成
【Flase】 - 下载失败
"""
url = 'https://webquoteklinepic.eastmoney.com/GetPic.aspx?'
params = {
'imageType': 'KXL' # 固定
}
# 获取本地secids
secids = read_secids()
piccode = None # 爬取到的图片编码
# 判断本地是否存储了secid
try:
secid_ = secids[str(code)]
secid = secid_ + str(code)
# 访问接口
params['nid'] = secid # 股票的secid
response = requests_get(url, params=params)
if isinstance(response, str):
# 如果返回的是str,说明访问有误
return False
# 无访问错误
piccode = response.content # 图片的编码
except KeyError:
print(f'本地未存储 {code} 的 secid 前缀')
pass
# 对比图片是否为暂无数据,如果是。可能secid错误
noneDatePIC = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\x08\x00\x00\x01m\x08\x03\x00\x00\x00U\xf3b%\x00\x00\x03\x00PLTE\x00\x00\x00\xff\xff\xff\x80\x80\x80\x03\x03\x03\x04\x04\x04\x05\x05\x05\x06\x06\x06\x07\x07\x07\x08\x08\x08\t\t\t\n\n\n\x0b\x0b\x0b\x0c\x0c\x0c\r\r\r\x0e\x0e\x0e\x0f\x0f\x0f\x10\x10\x10\x11\x11\x11\x12\x12\x12\x13\x13\x13\x14\x14\x14\x15\x15\x15\x16\x16\x16\x17\x17\x17\x18\x18\x18\x19\x19\x19\x1a\x1a\x1a\x1b\x1b\x1b\x1c\x1c\x1c\x1d\x1d\x1d\x1e\x1e\x1e\x1f\x1f\x1f !!!"""###$$$%%%&&&\'\'\'((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~\x7f\x7f\x7f\x80\x80\x80\x81\x81\x81\x82\x82\x82\x83\x83\x83\x84\x84\x84\x85\x85\x85\x86\x86\x86\x87\x87\x87\x88\x88\x88\x89\x89\x89\x8a\x8a\x8a\x8b\x8b\x8b\x8c\x8c\x8c\x8d\x8d\x8d\x8e\x8e\x8e\x8f\x8f\x8f\x90\x90\x90\x91\x91\x91\x92\x92\x92\x93\x93\x93\x94\x94\x94\x95\x95\x95\x96\x96\x96\x97\x97\x97\x98\x98\x98\x99\x99\x99\x9a\x9a\x9a\x9b\x9b\x9b\x9c\x9c\x9c\x9d\x9d\x9d\x9e\x9e\x9e\x9f\x9f\x9f\xa0\xa0\xa0\xa1\xa1\xa1\xa2\xa2\xa2\xa3\xa3\xa3\xa4\xa4\xa4\xa5\xa5\xa5\xa6\xa6\xa6\xa7\xa7\xa7\xa8\xa8\xa8\xa9\xa9\xa9\xaa\xaa\xaa\xab\xab\xab\xac\xac\xac\xad\xad\xad\xae\xae\xae\xaf\xaf\xaf\xb0\xb0\xb0\xb1\xb1\xb1\xb2\xb2\xb2\xb3\xb3\xb3\xb4\xb4\xb4\xb5\xb5\xb5\xb6\xb6\xb6\xb7\xb7\xb7\xb8\xb8\xb8\xb9\xb9\xb9\xba\xba\xba\xbb\xbb\xbb\xbc\xbc\xbc\xbd\xbd\xbd\xbe\xbe\xbe\xbf\xbf\xbf\xc0\xc0\xc0\xc1\xc1\xc1\xc2\xc2\xc2\xc3\xc3\xc3\xc4\xc4\xc4\xc5\xc5\xc5\xc6\xc6\xc6\xc7\xc7\xc7\xc8\xc8\xc8\xc9\xc9\xc9\xca\xca\xca\xcb\xcb\xcb\xcc\xcc\xcc\xcd\xcd\xcd\xce\xce\xce\xcf\xcf\xcf\xd0\xd0\xd0\xd1\xd1\xd1\xd2\xd2\xd2\xd3\xd3\xd3\xd4\xd4\xd4\xd5\xd5\xd5\xd6\xd6\xd6\xd7\xd7\xd7\xd8\xd8\xd8\xd9\xd9\xd9\xda\xda\xda\xdb\xdb\xdb\xdc\xdc\xdc\xdd\xdd\xdd\xde\xde\xde\xdf\xdf\xdf\xe0\xe0\xe0\xe1\xe1\xe1\xe2\xe2\xe2\xe3\xe3\xe3\xe4\xe4\xe4\xe5\xe5\xe5\xe6\xe6\xe6\xe7\xe7\xe7\xe8\xe8\xe8\xe9\xe9\xe9\xea\xea\xea\xeb\xeb\xeb\xec\xec\xec\xed\xed\xed\xee\xee\xee\xef\xef\xef\xf0\xf0\xf0\xf1\xf1\xf1\xf2\xf2\xf2\xf3\xf3\xf3\xf4\xf4\xf4\xf5\xf5\xf5\xf6\xf6\xf6\xf7\xf7\xf7\xf8\xf8\xf8\xf9\xf9\xf9\xfa\xfa\xfa\xfb\xfb\xfb\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff"\x1fv\x0c\x00\x00\x00\tpHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\xa8d\x00\x00\x050IDATx\x9c\xed\xdc\x81j\xe2Z\x14@\xd1\xf1\xfc\xffG\xbf\xd7\xdd\x18o\xc2@\xa5\x08m\x9c\xb5\x8a\xd6&6\x14\xdc9\xb9\xca0\x7fn\xf0\xbf??\xfd\x07\xf0;\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81|7\x84?\\\xdd\x8bB\xf8\xe6\xef\xf1[\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\xe1l>\xef\xe7\xaf;f}\xce[\x11\xc2\xd1|\xb8g0w\x1f\x8f\xb7\xaf\xcf\x1d\xf7}?\xf7\x87\xbe\x9a\x10Nz\xb1g\xfdy}\xb4\x84p\xdcyyB8\xd9&\xc2~\xb6\xcfc\xf3\xb6cy\x8a\x10\xbe8\xcc\xa5\xcdm\x1d\n\xfbk=s\x98\x04\xf3V\xf3@\x08g\xdb\x89\xbf,\x03\xb63\x7f\xb6\x12\xf6\x10L\x84\'\x0esis\\\rl\xeb\xc6\xc3rq\xce+\x89\xeb\x13\xc2\xd9\x1c\xce\xf59^#f\x1b\x06&\xc2s\x87\xb9\xb2Y\xee\x1f\xe7\xfd\xe3\x02q\xdf\xbc\x8c\x8dw \x84\xb3u"\xcc\xe36\xeb\xfb\xc79^?\xde\x81\x10\xce\x96\x89\xb0\xdfu\xbb\x7f\xac\xb4}six\xe20W\xb6~\x98\xb8oX\xde2\xec\x8b\x84\x9b\x89\xf0\xe5a\xb8\x1c!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x90W\x85\xc0\xd5\xbd&\x04\xde\x8c\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\x10\x88\xffU\xed\x9f\xf5\xa2\x10\xbe\xf9{\xfc\x16B B B B B B B B B B B B B B B B B B8\x9b\xcf\xfb\xf9\xeb\x8eY\x9f\xf3V\x84p4\x1f\xee\x19\xcc\xdd\xc7\xe3\xed\xebs\xc7}\xdf\xcf\xfd\xa1\xaf&\x84\x93^\xecY\x7f^\x1f-!\x1cw^\x9e\x10N\xb6\x89\xb0\x9f\xed\xf3\xd8\xbc\xedX\x9e"\x84/\x0esis[\x87\xc2\xfeZ\xcf\x1c&\xc1\xbc\xd5<\x10\xc2\xd9v\xe2/\xcb\x80\xed\xcc\x9f\xad\x84=\x04\x13\xe1\x89\xc3\\\xda\x1cW\x03\xdb\xba\xf1\xb0\\\x9c\xf3J\xe2\xfa\x84p6\x87s}\x8e\xd7\x88\xd9\x86\x81\x89\xf0\xdca\xael\x96\xfb\xc7y\xff\xb8@\xdc7/c\xe3\x1d\x08\xe1l\x9d\x08\xf3\xb8\xcd\xfa\xfeq\x8e\xd7\x8fw \x84\xb3e"\xecw\xdd\xee\x1f+m\xdf\\\x1a\x9e8\xcc\x95\xad\x1f&\xee\x1b\x96\xb7\x0c\xfb"\xe1f"|y\x18.G\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08\xe4U!pu\xaf\t\x817#\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04"\x04\xe2_1\xff\xb3^\x14\xc27\x7f\x8f\xdfB\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08D\x08g\xf3y?\x7f\xdd1\xebs\xde\x8a\x10\x8e\xe6\xc3=\x83\xb9\xfbx\xbc}}\xee\xb8\xef\xfb\xb9?\xf4\xd5\x84p\xd2\x8b=\xeb\xcf\xeb\xa3%\x84\xe3\xce\xcb\x13\xc2\xc96\x11\xf6\xb3}\x1e\x9b\xb7\x1d\xcbS\x84\xf0\xc5a.mn\xebP\xd8_\xeb\x99\xc3$\x98\xb7\x9a\x07B8\xdbN\xfce\x19\xb0\x9d\xf9\xb3\x95\xb0\x87`"<q\x98K\x9b\xe3j`[7\x1e\x96\x8bs^I\\\x9f\x10\xce\xe6p\xae\xcf\xf1\x1a1\xdb00\x11\x9e;\xcc\x95\xcdr\xff8\xef\x1f\x17\x88\xfb\xe6el\xbc\x03!\x9c\xad\x13a\x1e\xb7Y\xdf?\xce\xf1\xfa\xf1\x0e\x84p\xb6L\x84\xfd\xae\xdb\xfdc\xa5\xed\x9bK\xc3\x13\x87\xb9\xb2\xf5\xc3\xc4}\xc3\xf2\x96a_$\xdcL\x84/\x0f\xc3\xe5\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\x08\x81\xbc*\x04\xae\xee\xf8\x82\xfe\x07\x92\x00\xdbQIf\x9a\x8b\x00\x00\x00\x00IEND\xaeB`\x82'
if not piccode or piccode == noneDatePIC:
# 尝试所有secid
tryall = True # 如果tryall == True说明所有secid尝试失败
for tsecid_ in SECIDS:
print(f'下载图片 — 尝试{tsecid_}前缀')
params['nid'] = tsecid_ + str(code) # 股票的secid
response = requests_get(url, params=params)
if isinstance(response, str):
# 如果返回的是str,说明访问有误
return False
# 无访问错误
piccode = response.content # 图片的编码
if piccode != noneDatePIC:
tryall = False
print(f'下载图片成功!')
# 存储或改变secid前缀
secids[str(code)] = tsecid_
break
if tryall:
# 所有secid尝试失败
tryallsecidlog(f'download_stocktrend({code})\n')
return False
# 图片下载成功
with open(FILE_TEMPPIC, 'wb+') as temp_pic:
temp_pic.write(piccode)
write_secids(secids)
return True
def get_jjrank(ft="all", sc="6yzf", pn="50"):
"""
获取基金排名
:param ft: 类型(全部:all 股票:gp 混合:hh 指数:zs)
:param sc: 排行时间段(近一周:zzf 近1月:1yzf 近3月:3yzf 近6月:6yzf 近1年:1nzf 近3年:3nzf)
:param pn: 显示排行数
:return:
【'Time out'】 - 请求超时
【'Network error'】 - 网络连接错误
【'Response error'】 - 响应内容可能变更
【list】 - [
[
0_"基金代码", 1_"基金简称", 2_"首字母", 3_"最新日期", 4_"最新净值", 5_"累计净值", 6_"日增长率", 7_"近1周收益率",
8_"近1月收益率", 9_"近3月收益率", 10_"近6月收益率", 11_"近1年收益率", 12_"近2年收益率", 13_"近3年收益率",
14_"今年来收益率", 15_"成立以来收益率", 16_"成立日期", 17_"Unknown1", 18_"自定义收益率", 19_"Unknown2",
20_"Unknown3", 21_"Unknown4", 22_"手续费", 23_"Unknown5"
], ......
]
"""
# print(f'参数:{ft, sc, pn}')
url = "http://fund.eastmoney.com/data/rankhandler.aspx?"
headers = {
'User-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36',
'Connection': 'keep-alive',
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Host': 'fund.eastmoney.com',
'Referer': 'http://fund.eastmoney.com/data/fundranking.html'
}
params = {
"op": "ph",
"dt": "kf",
"ft": ft,
"sc": sc,
"st": "desc",
"pn": pn,
"dx": "1",
}
# 开始访问
response = requests_get(url, headers, params)
if isinstance(response, str):
# 访问出错
return response
# 访问成功,处理返回数据
data = response.text
start = data.index('[')
end = data.index(']')
data = data[start:end + 1]
try:
# 将处理完的数据转换成列表
data = eval(data)
except:
# 如果报错说明,返回的格式变更
responselog(url, params, response.text)
return 'Response error'
# 处理为嵌套列表
data_list = []
for line in data:
# print(line)
line2 = line.split(",")
# print(line2)
data_list.append(line2)
# 处理完成
return data_list
def get_jjbyname(key):
"""
按照基金名称是否包含关键字,获取基金列表
:param key: 名称
:return:
【'Time out'】 - 请求超时
【'Network error'】 - 网络连接错误
【'Response error'】 - 响应内容可能变更
【list】 - [
{'_id': '110022', 'CODE': '110022', 'NAME': '易方达消费行业股票', 'STOCKMARKET': ''},
......
]
"""
url = "http://fundsuggest.eastmoney.com/FundSearch/api/FundSearchPageAPI.ashx?"
headers = {
'User-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36',
'Connection': 'keep-alive',
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Host': 'fundsuggest.eastmoney.com',
'Referer': 'http://fund.eastmoney.com/'
}
params = {
"m": "1",
"key": key,
"pageindex": "0",
"pagesize": "1000",
}
# 开始访问
response = requests_get(url, headers, params)
if isinstance(response, str):
# 访问出错
return response
# 访问成功,处理返回数据
data = response.text
start = data.index('[')
end = data.index(']')
data = data[start:end + 1]
try:
# 将处理完的数据转换成列表
data = eval(data)
except:
# 如果报错说明,返回的格式变更
responselog(url, params, response.text)
return 'Response error'
return data
def get_jjheld(code: str, year):
"""
获取基金一年的股票持仓
:param code: str 基金代码
:param year: 年份
:return:
【'Time out'】 - 请求超时
【'Network error'】 - 网络连接错误
【None】 - 无数据
【dict】 - {
'截止': '2021-06-30',
'持仓': {
'表头': ['链接', '序号', '股票代码', '股票名称', '最新价', '涨跌幅', '相关资讯', '占净值比例', '持股数(万股)', '持仓市值(万元)']
'数据': [
[],......
]
}
}
"""
url = "http://fundf10.eastmoney.com/FundArchivesDatas.aspx?"
params = {
"type": "jjcc",
"code": code,
"topline": "10",
"year": year,
}
# 开始访问
response = requests_get(url, params=params)
if isinstance(response, str):
# 访问出错
return response
# print(f'相应数据:{response.text}')
# 访问成功开始分析数据
hp = Histheld() # html分析
hp.feed(response.text)
hp.close()
# 返回最新数据
if not hp.rslt:
# 无持仓数据,可能基金未公布财报
return None
# 有数据
return hp.rslt[0] # 返回最新的持仓
# ===============
# 分析基金持仓数据
# ===============
class Histheld(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.rslt = [] # 存储结果
self.adir = {} # 一个季度数据
self.hold = {
"表头": ['链接', '序号', '股票代码', '股票名称', '最新价', '涨跌幅', '相关资讯', '占净值比例', '持股数(万股)', '持仓市值(万元)'],
"数据": [],
} # 一个季度持仓
self.h4 = False # 获取截止日期标志位
self.h4_font = False # 截止日期。self.h4 and self.h4_font记录截止日期
self.table = False # 持仓数据获取标志位
self.tbody = False # 数据截取标志位
self.td = False
self.num = 0
self.herf = False # 截取链接
self.adata = "" # 存储一个单元格数据
self.linedata = [] # 存储一行数据
def handle_starttag(self, tag, attrs):
if tag == "h4":
self.h4 = True
elif tag == "font":
self.h4_font = True
elif tag == "tbody":
self.tbody = True
elif tag == "a" and self.num == 1: # 截取链接
for ats, value in attrs:
if ats == "href":
self.linedata.insert(0, value)
def handle_endtag(self, tag):
if tag == "h4":
self.h4 = False
elif tag == "font":
self.h4_font = False
elif tag == "tbody":
self.adir["持仓"] = self.hold.copy()
self.rslt.append(self.adir.copy())
self.hold["数据"] = []
self.tbody = False
elif tag == "td":
self.linedata.append(self.adata)
self.adata = ""
self.num += 1
elif tag == "tr" and self.tbody:
self.hold["数据"].append(self.linedata)
self.linedata = []
self.num = 0
def handle_data(self, data):
if self.h4 and self.h4_font:
self.adir["截止"] = data
elif self.tbody:
self.adata += data
def get_stock_daytrend(code: str, beg='0', end='20500000'):
"""
获取股票的哪个时间段的日K
:param code: 股票代码
:param beg: 20210101 开始时间,如果不传,表示从上市开始的日k
:param end: 结束时间,不传默认最新
:return:
【'TryAll error'】 - 所有secid尝试失败
【'Time out'】 - 超时
【'Network error'】 - 网络错误
【list】 - K线数据: ['日期,最高,最低', '2021-07-01,23.50,22.52', ......]
"""
url = 'http://push2his.eastmoney.com/api/qt/stock/kline/get?'
params = {
'fields1': 'f1,f3', # 股票信息:f1-股票代码,f3-股票名称
'fields2': 'f51,f54,f55', # f51-时间(2021-06-29 11:10),f54-最高,f55-最低
'klt': 101, # Unknow,必要的
'fqt': 1, # Unknow,必要的
'beg': beg,
'end': end,
}
# 获取本地secids
secids = read_secids()
data = None # 爬取到的数据
# 判断本地是否存储了secid
try:
secid_ = secids[str(code)]
secid = secid_ + str(code)
# 访问接口
params['secid'] = secid # 股票的secid
response = requests_get(url, params=params)
if isinstance(response, str):
# 如果返回的是str,说明访问有误
return response
# 无访问错误
jsondata = response.json()
# 判断返回是否有数据
if jsondata['data']:
data = jsondata['data']
except KeyError:
print(f'本地未存储 {code} 的 secid 前缀')
pass
# 如果data为空, 尝试所有可能的secid
if not data:
tryReponse = try_get(code, url, params=params)
if isinstance(tryReponse, str):
# 如果返回的是字符串,访问网址出错
return tryReponse
secid, jsondata = tryReponse
if not secid:
# 所有可能的secid尝试失败,可能股票代码错误,或其他
tryallsecidlog(f'get_stockinfo({code})\n')
return 'TryAll error'
else:
# 存储或改变secid
secids[str(code)] = secid
data = jsondata['data']
# 存储成功的secid
write_secids(secids)
return data['klines'] # 返回K线数据
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。