上一篇我們修改了資料庫
並且成功地把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這個地方
咱們下回分解~