python获取新浪财经可转债⾏情数据"""
author:汉江S
微博:汉江S
"""
quest import urlopen  # python⾃带爬⾍库
import pandas as pd
from datetime import datetime
import time
import re  # 正则表达式库
import os  # 系统库
import json  # python⾃带的json数据库
pd.set_option('expand_frame_repr', False)  # 当列太多时不换⾏
pd.set_option('display.max_rows', 5000)  # 最多显⽰数据的⾏数
# =====函数:从⽹页上抓取数据
def get_content_from_internet(url, max_try_num=10, sleep_time=5):
"""
使⽤python⾃带的urlopen函数,从⽹页上抓取数据
:param url: 要抓取数据的⽹址
:param max_try_num: 最多尝试抓取次数
:param sleep_time: 抓取失败后停顿的时间
:return: 返回抓取到的⽹页内容
"""
get_success = False  # 是否成功抓取到内容
# 抓取内容
for i in range(max_try_num):
try:
content = urlopen(url=url, timeout=10).read()  # 使⽤python⾃带的库,从⽹络上获取信息
get_success = True  # 成功抓取到内容
break
except Exception as e:
print('抓取数据报错,次数:', i+1, '报错内容:', e)
time.sleep(sleep_time)
# 判断是否成功抓取内容
if get_success:
return content
else:
raise ValueError('使⽤urlopen抓取⽹页数据不断报错,达到尝试上限,停⽌程序,请尽快检查问题所在')
# =====函数:从新浪获取指定股票的数据
def get_today_data_from_sinajs(code_list):
"""
返回⼀串股票最近⼀个交易⽇的相关数据
从这个⽹址获取股票数据:hq.sinajs/list=sh600000,sz000002,sz300001
正常⽹址:finance.sina/realstock/company/sh600000/nc.shtml,
:param code_list: ⼀串股票代码的list,可以多个,例如[sh600000, sz000002, sz300001],
:return: 返回⼀个存储股票数据的DataFrame
"""
# 构建url
url = "hq.sinajs/list=" + ",".join(code_list)
# 抓取数据
content = get_content_from_internet(url)
content = content.decode('gbk')
# 将数据转换成DataFrame
content = content.strip()  # 去掉⽂本前后的空格、回车等
data_line = content.split('\n')  # 每⾏是⼀个股票的数据
data_line = [i.replace('var hq_str_', '').split(',') for i in data_line]
df = pd.DataFrame(data_line, dtype='float')  #
# 对DataFrame进⾏整理
df[0] = df[0].str.split('="')
df['stock_code'] = df[0].str[0].str.strip()
df['stock_name'] = df[0].str[-1].str.strip()
df['candle_end_time'] = df[30] + '' + df[31]  # 股票市场的K线,是普遍以当跟K线结束时间来命名的
df['candle_end_time'] = pd.to_datetime(df['candle_end_time'])
rename_dict = {1: 'open', 2: 'pre_close', 3: 'close', 4: 'high', 5: 'low', 6: 'buy1', 7: 'sell1',
8: 'amount', 9: 'volume', 32: 'status'}  # ⾃⼰去对⽐数据,会有新的返现
# 其中amount单位是股,volume单位是元
df['status'] = df['status'].str.strip('";')
df = df[['stock_code', 'stock_name', 'candle_end_time', 'open', 'high', 'low', 'close', 'pre_close', 'amount',
'volume', 'buy1', 'sell1', 'status']]
return df
# test = get_today_data_from_sinajs(code_list=['sh000001','sz399001'])
# print(test)
# =====函数:判断今天是否是交易⽇
def is_today_trading_day():
"""
判断今天是否是交易⽇
:return: 如果是返回True,否则返回False
"""
# 获取上证指数今天的数据
df = get_today_data_from_sinajs(code_list=['sh000001','sz399001'])
sh_date = df.iloc[0]['candle_end_time']  # 上证指数最近交易⽇
# 判断今天⽇期和sh_date是否相同
w().date() == sh_date.date()
# test3 = is_today_trading_day()
# print(test3)
# =====函数:从新浪获取所有股票的数据
def get_all_today_stock_data_from_sina_marketcenter():
"""
vip.stock.finance.sina/mkt/#stock_hs_up
从新浪⽹址的上述的⽹址,逐页获取最近⼀个交易⽇所有股票的数据
:return: 返回⼀个存储股票数据的DataFrame
"""
# ===数据⽹址
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
}
#股票数据
raw_url = 'vip.stock.finance.sina/quotes_service/api/json_v2.php/HQNodeData?
page=%s' \
'&num=40&sort=symbol&asc=1&node=hs_a&symbol=&_s_r_a=sort'python正则表达式判断
#可转债数据
raw_url = 'vip.stock.finance.sina/quotes_service/api/json_v2.php/HQNodeDataSimple?page=%s&num=80&sort=symbol&asc=0&node=hskzz_z&_s_r_a=sort'    page_num = 1
# ===存储数据的DataFrame
all_df = pd.DataFrame()
# ===获取上证指数最近⼀个交易⽇的⽇期。此段代码在课程视频中没有,之后补上的
df = get_today_data_from_sinajs(code_list=['sh000001','sz399001'])
sh_date = df.iloc[0]['candle_end_time'].date()  # 上证指数最近交易⽇
# ===开始逐页遍历,获取股票数据
while True:
# 构建url
url = raw_url % (page_num)
print('开始抓取页数:', page_num)
# 抓取数据
content = get_content_from_internet(url)
content = content.decode('gbk')
# 判断页数是否为空
if'[]'in content:
print('抓取到页数的尽头,退出循环')
break
# 通过正则表达式,给key加上引号
content = re.sub(r'(?<={|,)([a-zA-Z][a-zA-Z0-9]*)(?=:)', r'"\1"', content)
# 将数据转换成dict格式
content = json.loads(content)
# 将数据转换成DataFrame格式
df = pd.DataFrame(content, dtype='float')
# 对数据进⾏整理
# 重命名
rename_dict = {'symbol': '股票代码', 'name': '股票名称', 'open': '开盘价', 'high': '最⾼价', 'low': '最低价',
'trade': '收盘价', 'settlement': '前收盘价', 'volume': '成交量', 'amount': '成交额'}
# 添加交易⽇期
df['交易⽇期'] = pd.to_datetime(sh_date)  # 在课程视频中使⽤的是上⼀⾏代码,现在改成本⾏代码,程序更加稳健
# 取需要的列
df = df[['股票代码', '股票名称', '交易⽇期', '开盘价', '最⾼价', '最低价', '收盘价', '前收盘价', '成交量', '成交额']]
# 合并数据
all_df = all_df.append(df, ignore_index=True)
# 将页数+1
page_num += 1
time.sleep(1)
# ===将当天停盘的股票删除,此段代码在课程视频中没有,之后补上的
all_df = all_df[all_df['开盘价'] - 0 > 0.00001]
set_index(drop=True, inplace=True)
# ===返回结果
return all_df
# test = get_all_today_stock_data_from_sina_marketcenter()
# print(test)
# 判断今天是否是交易⽇
if is_today_trading_day() is False:
print('今天不是交易⽇,不需要更新股票数据,退出程序')
exit()
# 判断当前时间是否超过15点
w().hour < 15:  # 保险起见可以⼩于16点
print('今天股票尚未收盘,不更新股票数据,退出程序')
exit()
# 获取今天所有的股票数据
df = get_all_today_stock_data_from_sina_marketcenter()
# 对数据进⾏存储
for i in df.index:
t = df.iloc[i:i+1, :]
stock_code = t.iloc[0]['股票代码']
# 构建存储⽂件路径
path = '../data/'+ stock_code + '.csv'
# ⽂件存在,不是新股
if ists(path):
<_csv(path, header=None, index=False, mode='a', encoding='gbk') # ⽂件不存在,说明是新股
else:
# 先将头⽂件输出
<_csv(path, index=False, mode='a', encoding='gbk')
print(stock_code)