上交所&深交所上市公司年報(bào)獲取

一個(gè)簡短的Python腳本,實(shí)現(xiàn)上市公司年報(bào)的獲取肤寝。

#上交所年報(bào)
import os
import time
import requests
from copy import deepcopy

URL_SSE = "http://www.sse.com.cn/disclosure/listedinfo/announcement/"
# 股票
URL_SSE_STOCK = "http://www.sse.com.cn/js/common/ssesuggestdata.js"
# 基金
URL_SSE_FUND = "http://www.sse.com.cn/js/common/ssesuggestfunddata.js"
# E債券
URL_SSE_EBOND = "http://www.sse.com.cn/js/common/ssesuggestEbonddata.js"
# T債券
URL_SSE_TBOND = "http://www.sse.com.cn/js/common/ssesuggestTbonddata.js"
# 查詢
URL_QUERY_COMPANY = "http://query.sse.com.cn/security/stock/queryCompanyBulletin.do"

URL_PDF = "http://static.sse.com.cn"

# 報(bào)告類型
REPORT_TYPE = {
    '全部': ('ALL', ''),
    '定期公告': ('ALL', 'DQBG'),
    '年報(bào)': ('YEARLY', 'DQBG'),
    '第一季度季報(bào)': ('QUATER1', 'DQBG'),
    '半年報(bào)': ('QUATER2', 'DQBG'),
    '第三季度季報(bào)': ('QUATER3', 'DQBG'),
    '臨時(shí)公告': ('ALL', 'LSGG'),
    '上市公司章程': ('SHGSZC', 'LSGG'),
    '發(fā)行上市公告': ('FXSSGG', 'LSGG'),
    '公司治理': ('GSZL', 'LSGG'),
    '股東大會(huì)會(huì)議': ('GDDH', 'LSGG'),
    'IPO公司公告': ('IPOGG', 'LSGG'),
    '其他': ('QT', 'LSGG'),
}

# 證券類型
SECURITY_TYPE = {
    '全部': '0101,120100,020100,020200,120200',
    '主板': '0101',
    '科創(chuàng)板': '120100,020100,020200,120200',
}

HEADER = {
    'Referer': URL_SSE,
    'User-Agent': "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
}

URL_PARAM = {
    # 是否分頁
    'isPagination': 'false',
    'productId': '600000',
    # 關(guān)鍵字
    'keyWord': '',
    'securityType': SECURITY_TYPE['全部'],
    'reportType2': 'DQBG',
    'reportType': 'YEARLY',
    'beginDate': '2016-07-17',
    'endDate': '2019-07-17',
}


def get_all_codes(url):
    res = requests.get(url)
    content = res.content.decode()
    tmp = content.split('_t.push({val:"')
    code, name, pinyin = [], [], []
    for i in tmp[1:]:
        item = i.split('"')
        code.append(item[0])
        name.append(item[2])
        pinyin.append(item[4])
    # print(code)
    return code, name, pinyin


def get_pdf_url(code, begin_date, end_date, security_type='全部', report_type='年報(bào)'):
    url_param = deepcopy(URL_PARAM)
    url_param['productId'] = code
    url_param['securityType'] = SECURITY_TYPE[security_type]
    url_param['reportType2'] = REPORT_TYPE[report_type][1]
    url_param['reportType'] = REPORT_TYPE[report_type][0]
    url_param['beginDate'] = begin_date
    url_param['endDate'] = end_date
    result = requests.get(URL_QUERY_COMPANY, params=url_param, headers=HEADER).json()['result']
    return [(URL_PDF + i['URL'], i['BULLETIN_TYPE'], i['BULLETIN_YEAR'], i['SSEDATE']) for i in result]


def save_pdf(code, pdf_title_urls, path='./'):
    file_path = os.path.join(path, code)
    if not os.path.isdir(file_path):
        os.makedirs(file_path)
    for url, r_type, year, date in pdf_title_urls:
        date = ''.join(date.split('-'))
        file_name = '_'.join([code, r_type, year, date]) + '.pdf'
        file_full_name = os.path.join(file_path, file_name)
        # print(file_full_name)
        rs = requests.get(url, stream=True)
        with open(file_full_name, "wb") as fp:
            for chunk in rs.iter_content(chunk_size=10240):
                if chunk:
                    fp.write(chunk)


def download_report(code):
    month_day = time.strftime('-%m-%d', time.localtime())
    year = int(time.strftime('%Y', time.localtime()))-3
    while True:
        year_3 = year - 3
        begin_date = str(year_3) + month_day
        end_date = str(year) + month_day
        pdf_urls = get_pdf_url(code, begin_date, end_date)
        # for i in title_urls:
        #     print(i)
        if pdf_urls:
            for i in range(1, 4):
                try:
                    save_pdf(code, pdf_urls)
                    break
                except Exception as e:
                    print(f'[{code}] 第{i}次嘗試下載出錯(cuò)', e)
            else:
                print(f'[{code}] 下載失敗')
        else:
            print(f'[{code}] 完畢')
            break
        year = year_3
        if year < 2011:
            break


def main():
    stock_codes, _, _ = get_all_codes(URL_SSE_STOCK)
    len_stock_codes = len(stock_codes)
    for index, code in enumerate(stock_codes):
        print(f'股票總數(shù):{len_stock_codes}, 已完成:{index}  ', end='')
        download_report(code)
    print('任務(wù)完成')


if __name__ == '__main__':
    main()

下面是深交所年報(bào)的Python腳本



import requests
import time
import pandas as pd
import random
import os
import json
import re

def validateTitle(title):
    rstr = r"[\/\\\:\*\?\"\<\>\|]"  # '/ \ : * ? " < > |'
    new_title = re.sub(rstr, "_", title)  # 替換為下劃線
    return new_title
# 定義爬取函數(shù)
def get_pdf_address(pageNum,start_date,end_date):
    url = 'http://www.szse.cn/api/disc/announcement/annList?random=%s' % random.random()
    headers = {'Accept': 'application/json, text/javascript, */*; q=0.01'
    ,'Accept-Encoding': 'gzip, deflate'
    ,'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8'
    ,'Content-Type': 'application/json'
    ,'Host': 'www.szse.cn'
    ,'Origin': 'http://www.szse.cn'
    ,'Proxy-Connection': 'keep-alive'
    ,'Referer': 'http://www.szse.cn/disclosure/listed/fixed/index.html'
    ,'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
    ,'X-Request-Type': 'ajax'
    ,'X-Requested-With': 'XMLHttpRequest'}
    pagenum = int(pageNum)
    payload = {"seDate":["{}-12-31".format(start_date),"{}-12-31".format(end_date)],"channelCode":["fixed_disc"],"bigCategoryId":["010301"],"pageSize":30,"pageNum":pagenum}
    r = requests.post(url,headers = headers,data = json.dumps(payload))
    result = r.json()
    return result

#創(chuàng)建一個(gè)DataFrame儲(chǔ)存爬取信息
data_download_pdf = pd.DataFrame(columns =['secCode','secName','url','title','publishTime'])
count = 0
url_head = 'http://disc.static.szse.cn/download/'
end = 2016
while end > 2006:
    start = end  - 2 
    result = get_pdf_address(1,start,end)
    print("開始爬取{}-12-31至{}-12-31的年報(bào)".format(start,end))
    pages = int(result['announceCount']/30 + 1)
    print("共%s頁" % pages)
    for i in range(1,pages):
        print("爬取深交所年報(bào)下載地址第{}頁".format(i))
        print("完成{}%".format(round(i/pages,4) * 100))
        result = get_pdf_address(i,start,end)
        num = len(result['data'])
        for each in range(num):
            secCode = result['data'][each]['secCode'][0]
            secName = result['data'][each]['secName'][0]
            url = url_head + result['data'][each]['attachPath']
            title = result['data'][each]['title']
            publishTime = result['data'][each]['publishTime']
            dict1 = {'secCode':secCode,'Name':secName,'url':url,'title':title,
                     'publishTime':publishTime}
            data_download_pdf = data_download_pdf.append(dict1, ignore_index=True )
        print('獲取完成')
        print("========================================")
        time.sleep(random.uniform(1,2)) # 控制訪問速度
    end = end - 2


print(data_download_pdf['title'])

 
    # print(file_full_name)
    
# 提取title中字符串獲取年份
data_download_pdf['Year'] = data_download_pdf['title'].str.extract('([0-9]{4})')

headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'}

for each in range(data_download_pdf.shape[0]):
    # each = 1 
    # pdf_url = "http://disc.static.szse.cn/download//disc/disk02/finalpage/2019-07-05/dde0ce5e-e2c7-4c09-b6f4-a03ad9d593ee.PDF"
    title=data_download_pdf.at[each,'title']
    title=validateTitle(title)
    code = data_download_pdf.at[each,'secCode']
    #name = data_download_pdf.at[each,'Name'].replace("*","")
    #name = data_download_pdf.at[each,'Name']
    #print(name)
    #year = data_download_pdf.at[each,'Year']
    print("開始下載股票代碼_{}_{}".format(code,title))
    path='./'
    file_path = os.path.join(path, code)
    if not os.path.isdir(file_path):
        os.makedirs(file_path)
    file_name = "{}_{}.pdf".format(code,title)
    file_full_name = os.path.join(file_path, file_name)
    
    pdf_url = data_download_pdf.at[each,'url'] 
    rs = requests.get(pdf_url,headers= headers, stream=True)
    with open(file_full_name, "wb") as fp:
        for chunk in rs.iter_content(chunk_size=10240):
            if chunk:
                fp.write(chunk)
    time.sleep(random.uniform(1,2)) # 控制訪問速度
    print("===================下載完成==========================")
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末钙姊,一起剝皮案震驚了整個(gè)濱河市送浊,隨后出現(xiàn)的幾起案子博秫,更是在濱河造成了極大的恐慌边灭,老刑警劉巖异希,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異绒瘦,居然都是意外死亡称簿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門椭坚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來予跌,“玉大人,你說我怎么就攤上這事善茎∪幔” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長烁焙。 經(jīng)常有香客問我航邢,道長,這世上最難降的妖魔是什么骄蝇? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任膳殷,我火速辦了婚禮,結(jié)果婚禮上九火,老公的妹妹穿的比我還像新娘赚窃。我一直安慰自己,他們只是感情好岔激,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布勒极。 她就那樣靜靜地躺著,像睡著了一般虑鼎。 火紅的嫁衣襯著肌膚如雪辱匿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天炫彩,我揣著相機(jī)與錄音匾七,去河邊找鬼。 笑死江兢,一個(gè)胖子當(dāng)著我的面吹牛昨忆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播划址,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼扔嵌,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了夺颤?” 一聲冷哼從身側(cè)響起痢缎,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎世澜,沒想到半個(gè)月后独旷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寥裂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年嵌洼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片封恰。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡麻养,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诺舔,到底是詐尸還是另有隱情鳖昌,我是刑警寧澤备畦,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站许昨,受9級(jí)特大地震影響懂盐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜糕档,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一莉恼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧速那,春花似錦俐银、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至榆俺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坞淮,已是汗流浹背茴晋。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留回窘,地道東北人诺擅。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像啡直,于是被迫代替她去往敵國和親烁涌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 整個(gè)圈子都在販賣焦慮販賣知識(shí)酒觅,放大自己生活的不如意撮执,放大90后的各種壓力。個(gè)人認(rèn)為每個(gè)時(shí)代都有每個(gè)時(shí)代賦予的意義舷丹,...
    Iris_Lu閱讀 121評(píng)論 0 0
  • 讀饒陽詩詞學(xué)會(huì)文章書懷 詩詞學(xué)會(huì)異凡塵抒钱,高雅才情震我魂。但愿胃腸江水洗颜凯,書山走馬上昆侖谋币。
    淇澳竹李聚生閱讀 82評(píng)論 0 1
  • “哪有!我覺得我可傻了症概,嘴巴笨蕾额,情商太低”顺牵” 微信小程序現(xiàn)在出了一個(gè)“群印象”的評(píng)價(jià)功能诅蝶,可以邀請(qǐng)不同好友給你貼標(biāo)...
    閑時(shí)來碗粥閱讀 1,070評(píng)論 0 5