现在股票的门户网站通过AJAX异步访问,获取数据难度有点大,不是专业的的人想要爬取点儿数据是真的不容易,我经过好久学习,终于皇天不负有心人找到了一个不用爬取就能获取股票历史数据的办法!!!——通过Tushare第三方数据库,将专业的事情交给专业的人去做!我们只负责使用数据。
我是参考的这篇文章,在他的代码的基础上做了一些改动,原作者实现的功能是数据库的不断更新,我修改了作者的代码之后实现的功能是批量的将数据传入到MySQL数据库中。
这个是原作者文章的地址:tushare使用教程(附代码)_晨沉辰的博客-CSDN博客
原作者将要实现的功能都封装成了方法,使用的时候直接调用,我也采用的这种方式,代码看起来就十分优雅。
# 使用接口
def get_token():
ts.set_token("209f020xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
pro = ts.pro_api()
return pro
到时候需要使用了直接打开一次就行
##获取所有股票的代码
def get_data_list(cursor, sql, conn):
cursor.execute(sql)
res = cursor.fetchall()
conn.commit()
#这两句话是Python代码,用于将一个元组列表转换为字符串列表。第一行代码将res转换为列表,
# 第二行代码使用了列表推导式和join()函数将每个元组中的元素连接成一个字符串,
# 然后将这些字符串连接成一个大字符串。最终结果是一个字符串列表。
ts_codes_list = list(res)
ts_codes_list = [",".join(list(x)) for x in ts_codes_list]
return ts_codes_list
这个是最核心的功能:
##获取数据
#从ts_codes_list中获取每日的股票数据,并返回一个DataFrame对象——daily
def get_data(stock, pro):
if stock[0]=='6':name=stock+'.SH'
elif stock[0]=='0' :name=stock+'.SZ'
else:name=stock+'.BJ'
daily = pd.DataFrame(columns=["ts_code", "trade_date", "open", "high","low","close", "pre_close","pct_chg","vol","amount"])#创建daily对象
# for i in range(0, len(ts_codes_list), 100):#每次从ts_codes_list里面取100个数据,从0开始,到列表结束为止
# j = i + 100 #设定一个游标,最后省下不够100的时候,按照实际长度来作为操作的长度
# if (j >= len(ts_codes_list)):
# j = len(ts_codes_list)
# name = ",".join(ts_codes_list[i:j])#将从i到j的100条股票代码数据加入到字符串中
part = pro.daily(ts_code=name,start_date=20100101, end_date=get_yesterday_date())[#获取的部分数据
["ts_code", "trade_date", "open", "high","low","close", "pre_close","pct_chg","vol","amount"]]#【代码,交易日期,开盘,结束,涨跌额度,昨天收盘价】
daily = pd.concat([daily, part], ignore_index=True)#用于将两个DataFrame对象daily和part沿着行方向拼接
#将daily中的trade_date列的值转换为get_date_format函数返回的格式。apply是一个DataFrame对象的方法,
# 它可以对每个元素或每行或每列应用一个函数,并返回一个新的对象。
#将日期格式改变为
daily["trade_date"] = daily["trade_date"].apply(get_date_format)
return daily
个人感觉我的注释做的还算可以,又不懂的小伙伴可以私聊我
这是全部的代码:
import tushare as ts
import pandas as pd
import datetime
from sqlalchemy import create_engine
from decimal import Decimal
import pymysql
import warnings
warnings.filterwarnings("ignore")
# 使用接口
def get_token():
ts.set_token("209f020xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
pro = ts.pro_api()
return pro
##获取所有股票的代码
def get_data_list(cursor, sql, conn):
cursor.execute(sql)
res = cursor.fetchall()
conn.commit()
#这两句话是Python代码,用于将一个元组列表转换为字符串列表。第一行代码将res转换为列表,
# 第二行代码使用了列表推导式和join()函数将每个元组中的元素连接成一个字符串,
# 然后将这些字符串连接成一个大字符串。最终结果是一个字符串列表。
ts_codes_list = list(res)
ts_codes_list = [",".join(list(x)) for x in ts_codes_list]
return ts_codes_list
# mysql连接之前,先得到conn和游标
def start_con():
conn = pymysql.connect(
host="localhost",
user="root", password="1234",
database="history",
charset="utf8")
cursor = conn.cursor()
return conn, cursor
#获得截止到昨天的时日期数据
def get_yesterday_date():
now_time = datetime.datetime.now()#获得当前日期数据
date = (now_time + datetime.timedelta(days=-1)).strftime("%Y%m%d") # 获取后一天
return date
def get_date_format(x):#将输入的日期字符串x转换为"YYYY/MM/DD"格式。具体实现方式是将字符串x按照年、月、日的顺序分割,然后用"/"连接起来
return x[:4] + "/" + x[4:6] + "/" + x[6:]
##获取数据
#从ts_codes_list中获取每日的股票数据,并返回一个DataFrame对象——daily
def get_data(stock, pro):
if stock[0]=='6':name=stock+'.SH'
elif stock[0]=='0' :name=stock+'.SZ'
else:name=stock+'.BJ'
daily = pd.DataFrame(columns=["ts_code", "trade_date", "open", "high","low","close", "pre_close","pct_chg","vol","amount"])#创建daily对象
# for i in range(0, len(ts_codes_list), 100):#每次从ts_codes_list里面取100个数据,从0开始,到列表结束为止
# j = i + 100 #设定一个游标,最后省下不够100的时候,按照实际长度来作为操作的长度
# if (j >= len(ts_codes_list)):
# j = len(ts_codes_list)
# name = ",".join(ts_codes_list[i:j])#将从i到j的100条股票代码数据加入到字符串中
part = pro.daily(ts_code=name,start_date=20100101, end_date=get_yesterday_date())[#获取的部分数据
["ts_code", "trade_date", "open", "high","low","close", "pre_close","pct_chg","vol","amount"]]#【代码,交易日期,开盘,结束,涨跌额度,昨天收盘价】
daily = pd.concat([daily, part], ignore_index=True)#用于将两个DataFrame对象daily和part沿着行方向拼接
#将daily中的trade_date列的值转换为get_date_format函数返回的格式。apply是一个DataFrame对象的方法,
# 它可以对每个元素或每行或每列应用一个函数,并返回一个新的对象。
#将日期格式改变为
daily["trade_date"] = daily["trade_date"].apply(get_date_format)
return daily
# 将数据写入到表格中
def to_mysql_pro(code,data):
# 建立连接,username替换为用户名,passwd替换为密码,test替换为数据库名
# conn = create_engine('mysql+pymysql://root:NEULYP@39.99.252.203/JZ_QM',encoding='utf8')
conn = create_engine('mysql+pymysql://root:1234@localhost/history', encoding='utf8')
# 写入数据,table_name为表名,‘replace’表示如果同名表存在就替换掉
#将data中的数据写入到conn连接的数据库中的pro_yield表中,如果表已经存在,则追加数据,不保留索引列
pd.io.sql.to_sql(data, f"{code}_history_day", conn, if_exists='append', index=False)#用于将DataFrame对象data插入到数据库表"pro_yield"中
def creat_table(code,cursor):
drop_table=f'drop table if exists {code}_history_day;'
sql_create_table=f'create table {code}_history_day (ts_code varchar(10), trade_date datetime(6), open double(10,2), high double(10,2),low double(10,2),close double(10,2), pre_close double(10,2),pct_chg double(10,2),vol double(10,2),amount double(10,2))'
cursor.execute(drop_table)
cursor.execute(sql_create_table)
if __name__ == '__main__':
sql_read_stocks='select 代码 from stock_main'
pro=get_token()
conn,cursor=start_con()
stocks=get_data_list(cursor,sql_read_stocks,conn)#得到全部的股票字符串列表
stocks[1300::]
for stock in stocks:
# conn, cursor = start_con()
creat_table(stock,cursor)
data = get_data(stock, pro) # 得到截止到昨天的所有数据
to_mysql_pro(stock,data)