[Day 19] 第一主餐 pt.11-财报资料,我全都要

上一篇我们修改了资料库
并且成功地把BeautifulSoup的资料送到Database内了
今天我们就要来把所有的资料都捞进Database啦
废话不多说,咱们累狗

能自动就不要手动 - 一键捞取所有财报

上一篇我们把单一的公司季财报捞出来了
这边我们准备把所有公司的所有财报捞出来啦
啊对,捞之前记得清Django的Database

今天我们不会进django看看他了
毕竟models views那些东东我们都架好了
今天就只会改BeautifulSoup的部分
首先最重要的,就是先找所有公司代码
这里我们就要改去台湾证券交易所啦
https://www.twse.com.tw/zh/page/listed/listed_company/new_listing.html
这里就是所有上市公司
可是他的预设只有10笔公司怎办呢
没关系,咱们看看上面有"列印/HTML"
这里点进去就可以看到所有公司啦

那这边的url自然就是所有公司的HTML原始码连结啦
废话不多说,捞

import requests
import json
from bs4 import BeautifulSoup
# 所有上市公司列表url
url = 'https://www.twse.com.tw/company/newlisting?response=html&yy='
# 取得所有上市公司原始码
res = requests.get(url=url)
# 用BeautifulSoup分析HTML
soup = BeautifulSoup(res.text, 'html.parser')
# 取得table内容
table_body = soup.find("tbody")
# 将所有公司id存成list
all_comp_id = []
#将每个tr取出
for i in table_body.find_all('tr'):
    #取出公司ID
    inte = i.find_all('td')[0].getText()
    # 6位数代码为存托公司,不在我们分析范围,因此剔除
    if int(inte) < 100000:
        all_comp_id.append(all_comp_id)

这样我们就把所有公司捞出来啦

接下来就是把公司每季财报捞出来啦
这里我们先回头看原本POST的data

data={
        'co_id': '1201',
        'queryName': 'co_id',
        'inputType': 'co_id',
        'isnew': 'true',
        'TYPEK': 'all',
        'encodeURIComponent': '1',
        'step': '1',
        'firstin': '1',
        'off': '1',
        'year': None,
        'season': None
}

可以看到co_id就是公司id部分啦
然後这里isnew代表是否直接捞最新财报
这里我们改成false
然後我们捞财报的范围根据查询只有105年~109年的资料
然後109年只有两季
所以我们要写一个回圈去改data内year跟season的
所以我们的data先改写成这样

data={
        'co_id': co_id,
        'queryName': 'co_id',
        'inputType': 'co_id',
        'isnew': 'false',
        'TYPEK': 'all',
        'encodeURIComponent': '1',
        'step': '1',
        'firstin': '1',
        'off': '1',
        'year': year,
        'season': season
}

然後python有个range可以迭代范围内的数字
记得range含头不含尾
所以我们的回圈写成如下:

for year in range(105, 110): #105含,110不含
    season_range = 4 #预设捞四季财报
    if year == 109:
        season_range = 2 #若是109年则只捞前2
    for season in range(1, season_range+1): #从1开始到n
        for co_id in all_comp_id: #刚刚存的所有公司id
        ...

最後有些公司可能是在106年後建立的
所以可能会有找不到财报的情况
就像最知名的八方云集,108年第一季就没有财报

老牌公司味全就有108第一季财报

因此我们万一没捞到财报就要跳过
这特徵也不难找,反正找不到财报时就会跳"查询无资料"
所以我们就设一个条件,如果在汤里面找到"查询无资料"这个字串就跳过
如下面code所示

if bool(soup.findAll(text="查询无资料")):
    print("查询无资料")
    continue

把以上CODE加上之前写的CODE合并,我们的BeautifulSoup的code部分应该就会变成如下

import requests
import json
from bs4 import BeautifulSoup

#================捞取所有公司part==================
# 所有上市公司列表url
url = 'https://www.twse.com.tw/company/newlisting?response=html&yy='
# 取得所有上市公司原始码
res = requests.get(url=url)
# 用BeautifulSoup分析HTML
soup = BeautifulSoup(res.text, 'html.parser')
# 取得table内容
table_body = soup.find("tbody")
# 将所有公司id存成list
all_comp_id = []
#将每个tr取出
for i in table_body.find_all('tr'):
    #取出公司ID
    inte = i.find_all('td')[0].getText()
    # 6位数代码为存托公司,不在我们分析范围,因此剔除
    if int(inte) < 100000:
        all_comp_id.append(inte)
        
#================捞取财报part==================
for year in range(105, 110): #105含,110不含
    season_range = 4 #预设捞四季财报
    if year == 109:
        season_range = 2 #若是109年则只捞前2
    for season in range(1, season_range+1): #从1开始到n
        for co_id in all_comp_id: #刚刚存的所有公司id
            sheet_url = 'https://www.twse.com.tw/company/newlisting?response=html&yy='
            data={
                    'co_id': co_id,
                    'queryName': 'co_id',
                    'inputType': 'co_id',
                    'isnew': 'false',
                    'TYPEK': 'all',
                    'encodeURIComponent': '1',
                    'step': '1',
                    'firstin': '1',
                    'off': '1',
                    'year': 108,
                    'season': 1
            }
            headers = {
                #'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36',
            }
            res = requests.post(url=sheet_url,data=data,headers=headers)
            soup = BeautifulSoup(res.text, 'html.parser')
            #若查询无资料,则显示该公司该年该季度查询无资料之提示,并直接进行下一回圈
            if bool(soup.findAll(text="查询无资料")):
                print("公司代码:{} {}年{}季 查询无资料".format(comp_id, year ,season))
                continue
            tr_tag = soup.find_all("tr", {"class": ["odd", "even"]})
            data_table = {} #公司财务报表
            balance_sheet = {} #负债表
            income_statement = {} #损益表
            for i in tr_tag:
                td_tag = i.find_all("td")
                if len(td_tag) == 3: #三个td tag代表为负债表资料
                    inner = []
                    for j in td_tag:
                        inner.append(j.getText())
                    balance_sheet[inner[0]] = {'金额': inner[1], '百分比': inner[2]}
                if len(td_tag) == 5: #五个td tag代表为损益表资料
                    inner = []
                    for j in td_tag:
                        inner.append(j.getText())
                    income_statement[inner[0]] = {'金额': inner[1], '预测金额': inner[2], '年度财务预测达成率': inner[3], '截至第2季止财务预测季达成率': inner[4]}
            url = "http://172.16.15.123:8000/stonks/set_stonks_data/"
            data={'comp_id':co_id,
                'year':year,
                'season':season,
                'balance_sheet':json.dumps(balance_sheet),
                'income_statement':json.dumps(income_statement)}
            res_post = requests.post(url=url,data=data,headers=headers)
            
            #如果回传status code非200,则代表出错,印出该公司该年度该季财报错误
            if res_post.status_code != 200: 
                print("公司代码:{} {}年{}季 存入资料库错误".format(comp_id, year ,season))
                
            #若回传200则提示成功讯息
            else:
                print("公司代码:{} {}年{}季 存入资料库成功".format(comp_id, year ,season))

最後执行

成功啦~剩下等他自动执行完毕就好了

以上就是自动捞取所有财报的内容啦
然後先预告一下
由於本人明天要回台中
因此下一篇会再做一次中场休息
我们会来讲一下github这个东东,以及如何把你的code丢到github上
想知道如何把你的code存到github这个地方
咱们下回分解~


<<:  DAY 15 - 哥布林 (2)

>>:  【Day17】数据展示元件 - Infinite scroll

(Day 19) 原型与建构式

函式建构式建立原型 前面几篇有提到,可以使用函示建构式、或是 ES 6 来建立原型,今天就来介绍使用...

[Day_1] Python基础小教室

嗨~大家好, 接下来是为期一个月的铁人挑战 print('Day_1') 今天是想先跟大家做跟心灵喊...

DAY7-EXCEL统计分析:统计学是什麽?

在我们学习统计学之前应该清楚理解何谓统计学,这样才能够学以致用,并有效利用excel等工具来帮助我们...

菜鸟日记Day 29-用Chart.js制作图表

原本要使用C3.js搭配D3.js套件制作动态图表,但不知为何一直无法正常抓取D3.js的cdn档案...

食谱搜寻系统MySQL下载+测试

Mysql下载 因为网路上已经有很多下载教学了,icebear也是参考网路上下载的,所以在这里就不多...