抓取下载A股公司财报数据

要做针对股票做量化分析和交易,免不了试需要抓取数据,虽然现在不少券商提供了量化API接口,但要么收费,要么对调用次数有限制。有些初学者或者临时做个分析,不想搞这么复杂,那么抓取网上的数据,是一个比较简单有效的方法。这里就分享我抓取数据用到的一些代码。

A股上市公司列表

公司财报、股价K线数据,有很多方式可以抓取,但是抓取基本都是基于公司股票代码,比如sh600001,sz000001。如何获取所有A股公司的股票代码,是经常遇到的问题。网上有很多分享抓取股票代码的方式,比如利用抓取http://quote.eastmoney.com/stock_list.html的内容来解析出一个列表出来,但是这个方式已经不太好用,因为这个页面已经经过了javascript改造,此外做了分页,抓取起来要麻烦很多。

目前这部分还没有研究可行的新方法,这里提供一个2020年初的一个列表先用着。 https://github.com/innerpeace-forever/financial/blob/master/data/stock_list.txt

财报数据抓取

如果着急的话,可以直接看代码: https://github.com/innerpeace-forever/financial/blob/master/report_downloader.py

运行环境是Python 3.7.3,这个代码用Python 2的版本必然会出现各种错误,比如encoding、pandas的问题。

财报的数据源是网易的财经数据: http://quotes.money.163.com

# -*- coding: utf-8 -*-
from os import makedirs
from os.path import join
import json

import requests
from pandas import DataFrame

## tag可以是以下:
## zcfzb:资产负债表
## lrb:利润表
## xjllb:现金流量表
def download_financial_table(stock_code, tag):
    url = "http://quotes.money.163.com/service/%s_%s.html" % (tag, stock_code)
    html = requests.get(url)
    html.encoding = "gbk"
    items = html.text.split('\n')
    index = items[0].split(',')[1:-1]
    data = {}
    for item in items:
        t = item.strip().split(',')
        if len(t) == 1:
            continue
        data[t[0]] = t[1:-1]

    # 由于财报原始数据包含季度财报,这里通过这个list来提取年报数据
    date_list = ['2019-12-31', '2018-12-31', '2017-12-31', '2016-12-31', '2015-12-31']
    df = DataFrame(data, index=index)
    df = df[df['报告日期'].isin(date_list)]

    if df.shape[0] < 5:
        return 0

    dir_path = "./csv/%s" % stock_code
    makedirs(dir_path, exist_ok=True)
    file_path = join(dir_path, "%s_%s.csv" % (stock_code, tag))
    df.to_csv(file_path, index=True, encoding="gbk")
    return df.shape[0]

抓取K线数据

K线数据有很多方式抓取,腾讯的API还是比较稳定,一般我会使用腾讯的API(qtimq.cn)。

# -*- coding: utf-8 -*-
from os import makedirs
from os.path import join
import json

import requests
from pandas import DataFrame

def download_k(stock_code):
    if stock_code[0] == '6':
        tag = 'sh'
    else:
        tag = 'sz'
    full_code = "%s%s" % (tag, stock_code)

    # 可以自己指定其它时间。其中2019-12-31是起始时间,2020-12-01是结束时间,
    # 300是天数(其实没有用,但是还必须有个数,否则返回数据有问题)
    url = "http://web.ifzq.gtimg.cn/appstock/app/fqkline/get?param=%s,day,2019-12-31,2020-12-01,300,qfq" % (full_code)
    html = requests.get(url)
    data = json.loads(html.text)

    # 有一些公司有分红或者拆股,价格会出现前复权(qfq)的标记,所以需要做一个识别
    if 'qfqday' in data['data'][full_code]:
        key = 'qfqday'
    elif 'day' in data['data'][full_code]:
        key = 'day'
    else:
        key = 'day'

    df = DataFrame(data['data'][full_code][key][:][:])
    df = DataFrame(df[[0, 1, 2, 3, 4, 5]])
    df.columns = ['date', 'start', 'end', 'high', 'low', 'volume']

    dir_path = "./csv/%s" % stock_code
    makedirs(dir_path, exist_ok=True)
    file_path = join(dir_path, "%s_%s.csv" % (stock_code, 'kline'))
    df.to_csv(file_path, index=False, encoding="gbk")