10分钟爬取A股所有上市公司超千万条股票数据

最近,在tushare官方文档中,看到这个一个方法pro.stock_basic(),作用是可以爬取A股所有上市股票基本信息。然后我就试了一下,默认条件下可以爬取到A股上市的的所有股票基本数据,共4179条数据(截止20210306),数据主要包括股票代码、公司名称、公司地点、上市板块以及上市日期。

 

ts_code	symbol	name	area	industry	market	list_date
0	000001.SZ	000001	平安银行	深圳	银行	主板	19910403
1	000002.SZ	000002	万科A	深圳	全国地产	主板	19910129
2	000004.SZ	000004	国华网安	深圳	互联网	主板	19910114
3	000005.SZ	000005	世纪星源	深圳	环境保护	主板	19901210
4	000006.SZ	000006	深振业A	深圳	区域地产	主板	19920427
...	...	...	...	...	...	...	...
4174	688777.SH	688777	中控技术	浙江	软件服务	科创板	20201124
4175	688788.SH	688788	科思科技	深圳	通信设备	科创板	20201022
4176	688819.SH	688819	天能股份	浙江	电气设备	科创板	20210118
4177	688981.SH	688981	中芯国际-U	上海	半导体	科创板	20200716
4178	689009.SH	689009	九号公司-UWD	北京	专用机械	CDR	20201029
4179 rows × 7 columns

拿到这些数据之后,发现并没有什么实际用途。突然有了一个大胆的想法——要不把A股所有上市公司的股票都爬下来?

图片

tushare也提供了一个接口可以直接爬取A股股票数据——daily

我也是一波操作猛如“虎”,直接挨个爬取。结果耗时一个多小时。等完这一个多小时,感觉真心累。心想着赶紧把数据入库保存,今天的任务就结束了(现在心想,要是先保存到文件再入库,爬的数据就不会丢失了,都是坑啊)。

1000W多的数据,我使用sqlalchemy直接插入数据库,心想着快点结束。

可造化弄人,执行几分钟后,浏览器直接卡死,紧接着电脑卡死,一度出现类似于BIOS的界面。最后只能重启电脑。搞了一下午的数据,结果就这么没了。这一波,我笑了,不知道为什么。

图片

事后,进行分析后发现,在开始爬取时,基本每秒可以爬取100多支股票左右,稳定之后每分钟基本可以爬取60支左右,该接口限制每分钟最多不超过500次,如果只用单线程爬,是不是太对不起500次的限制了。

如果可以使用多线程,每分钟累计只要不超过500次就可以了。如果设置7个线程,在开始1分钟内时,会超过500。你会看到下面这样的错误信息:

 

Exception: 抱歉,您每分钟最多访问该接口500次,权限的具体详情访问:https://tushare.pro/document/1?doc_id=108。

所以在开始的时候使用6个线程跑,等3分钟之后,这6个线程稳定之后,每分钟累加差不多每分钟可以爬取360支股票左右。开始启动第7个线程。

不过保险期间,代码中还需要添加异常处理,防止网络超时或者今天网速太快,一下子超过500的限制。核心代码如下:

# 备份
def getStockTread(listDic,threadname):
    dt = pd.DataFrame()
    dt_sz = pd.DataFrame()
    dt_temp = []
    total = len(listDic)
    filename=threadname+'.csv'
    i = 0
    for x in listDic:
        i = i+1
        if(i % 5==0 or i==total):
            print("----线程名:",threadname,", Total:",total,"正在查询第",i," 个,进度",format(i/total*100,'.2f'),"%-----")
        try:
            dt_temp = pro.daily(ts_code=x["tscode"])
        except:
            #将当前错误数据重新插入list中,并停止运行30s。防止网络超时或者超过500次接口报错
            listDic.append(x)
            time.sleep(30)
            continue
        else:    
            dt_temp = dt_temp[["ts_code","trade_date","close","open","high","low","pre_close","change","pct_chg","vol","amount"]]
            dt_sz= dt_sz.append(dt_temp)
    dt_sz.rename(columns={'ts_code':'stock','trade_date':'date','pre_close':'preclose','pct_chg':'pctchange'},inplace = True)
    dt=dt.append(dt_sz)
    #将数据写入文件,防止其他原因造成数据丢失
    dt.to_csv(filename, index=False)
    return dt


 

方法写好了,现在开始启动7个线程,其中第7个线程需等待3分钟之后开始执行。

import _thread

# stockTread = getStockTread(stock_list)

try:
    _thread.start_new_thread( getStockTread, (stock_list[:625],"Thread-1"), )
    _thread.start_new_thread( getStockTread, (stock_list[625:1250],"Thread-2" ) )
    _thread.start_new_thread( getStockTread, (stock_list[1250:1875],"Thread-3" ) )
    _thread.start_new_thread( getStockTread, (stock_list[1875:2500],"Thread-4" ) )
    _thread.start_new_thread( getStockTread, (stock_list[2500:3125],"Thread-5" ) )
    _thread.start_new_thread( getStockTread, (stock_list[3125:3750],"Thread-6" ) )
    time.sleep(180)
    _thread.start_new_thread( getStockTread, (stock_list[3750:],"Thread-7" ) )
except:
   print ("Error: 无法启动线程")

 

图片

这次通过先后共开启7个线程,耗时12分钟左右,较第一次的一个多小时,提升速度还是很明显的。执行结束后,每个线程获取到的数据都写到csv文件中,在本地保存。

图片

至于这1000W条数据怎么快速入库,下次再和大家分享

 

图片


版权声明:本文为wzgl__wh原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。