Photo by CardMapr.nl on Unsplash
Python網頁爬蟲在日常生活中有非常多的應用,股票分析就是其中之一,利用Python網頁爬蟲自動化爬取的特性,蒐集所需的各個公司股價資訊。但是隨著經濟的變動,關注的股票代碼時常會進行調整,這時候,該如何讓Python網頁爬蟲有彈性的讀取股票代碼就很重要。
而資料庫就是實務上最常使用的資料儲存工具,本文就以SQLite資料庫為例,來和大家分享Python網頁爬蟲如何動態讀取資料庫中所要分析的股票代碼資料,來爬取臺灣證券交易所的個股日成交資訊。其中的實作步驟包含:
- 分析網頁結構
- 開發Python網頁爬蟲
- 建置SQLite資料庫
- Python網頁爬蟲讀取資料庫
一、分析網頁結構
截取自臺灣證券交易所個股日成交資訊https://www.twse.com.tw/zh/page/trading/exchange/STOCK_DAY.html
由於查詢結果是依據使用者動態輸入的股票代碼,到網頁伺服端撈取相應的資料,所以,這時候可以按下F12,切換到Network(網路)頁籤,並且再次按下查詢按鈕,來觀察網頁背後的請求情形,如下圖:相信讀者應該已經知道,透過替換網址中的date日期與stockNo股票代碼參數,就能夠動態爬取所要分析的公司股票資料。
二、開發Python網頁爬蟲
知到了網址之後,利用以下指令安裝requests發送請求的套件:
$ pip install requests
開啟Visual Studio Code程式碼編輯器,建立app.py檔案,引用開發所需的以下模組(Module):
from datetime import datetime import requests import sqlite3
接下來,利用requests模組(Module)發送請求到查詢結果的網址,並且透過json()函式轉為字典(Dictionary)後,存取data(查詢結果)欄位,如下範例:
from datetime import datetime import requests import sqlite3 response = requests.get( f'https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date=20210806&stockNo=2330') response_data = response.json()['data'] print(response_data)
執行結果:
[['110/08/02', '24,948,096', '14,593,329,483', '583.00', '590.00', '580.00', '590.00', '+10.00', '19,791'], ['110/08/03', '28,104,984', '16,655,446,605', '594.00', '594.00', '590.00', '594.00', '+4.00', '20,221'], ['110/08/04', '23,714,971', '14,132,827,829', '598.00', '598.00', '594.00', '596.00', '+2.00', '18,228'], ['110/08/05', '15,673,765', '9,343,887,536', '598.00', '598.00', '593.00', '596.00', ' 0.00', '15,495'], ['110/08/06', '13,994,018', '8,275,142,201', '596.00', '596.00', '588.00', '591.00', '-5.00', '13,742']]
由於我們是要取得當日的成交資訊,這時候就可以利用Python Comprehension語法,透過迴圈讀取以上的網頁回應資料,並且判斷如果有當天的日期,則將資料取出來,如下範例:
from datetime import datetime import requests import sqlite3 response = requests.get( f'https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date=20210806&stockNo=2330') response_data = response.json()['data'] result = [data for index, data in enumerate(response_data) if '110/08/06' in response_data[index]] print(result)
執行結果
[['110/08/06', '13,994,018', '8,275,142,201', '596.00', '596.00', '588.00', '591.00', '-5.00', '13,742']]
當然,日期的部分會建議Python網頁爬蟲能夠自動帶入當天的日期,就可以使用datetime模組(Module)來取得當下的日期與指定格式,如下範例第6、7行:
from datetime import datetime import requests import sqlite3 today = datetime.now().strftime('%Y%m%d') #西元年(yyyymmdd) chinese_today = f"{(datetime.now().year - 1911)}/{datetime.now().strftime('%m/%d')}" #民國年(yyy/mm/dd) response = requests.get( f'https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date=20210806&stockNo=2330') response_data = response.json()['data'] result = [data for index, data in enumerate(response_data) if '110/08/06' in response_data[index]] print(result)
設定完成後,將第10行的請求網址date日期參數與第13行的民國日期改為使用變數的方式帶入,如下範例:
from datetime import datetime import requests import sqlite3 today = datetime.now().strftime('%Y%m%d') #西元年(yyyymmdd) chinese_today = f"{(datetime.now().year - 1911)}/{datetime.now().strftime('%m/%d')}" #民國年(yyy/mm/dd) response = requests.get( f'https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date={today}&stockNo=2330') response_data = response.json()['data'] result = [data for index, data in enumerate(response_data) if chinese_today in response_data[index]] print(result)
另外,為了方便後續的資料識別,所以當日如果有成交資料的話,則在串列(List)中的第一個位置增加股票代碼,如下範例第15、16行:
from datetime import datetime import requests import sqlite3 today = datetime.now().strftime('%Y%m%d') #西元年(yyyymmdd) chinese_today = f"{(datetime.now().year - 1911)}/{datetime.now().strftime('%m/%d')}" #民國年(yyy/mm/dd) response = requests.get( f'https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date={today}&stockNo=2330') response_data = response.json()['data'] result = [data for index, data in enumerate(response_data) if chinese_today in response_data[index]] if result: #如果有資料 result[0].insert(0, '2330') print(result)
執行結果
[['2330', '110/08/06', '13,994,018', '8,275,142,201', '596.00', '596.00', '588.00', '591.00', '-5.00', '13,742']]
三、建置SQLite資料庫
到目前為止,都只有爬取單一公司的當日成交資料,接下來,就要讓Python網頁爬蟲動態讀取資料庫中,我們所自訂的多個股票代碼。
而在這之前,就需要先建立一個資料庫,大家可以下載DB Browser for SQLite工具,來建立SQLite資料庫,開啟後如下圖:
點擊「新建資料庫」,命名為「Stocks.db」,並且存放在專案資料夾中,如下圖:接著,命名資料表為「StockNumbers」,以及新增「StockNo」欄位,類型為「TEXT」,如下圖:
四、Python網頁爬蟲讀取資料庫
SQLite資料庫建置完成,開啟app.py檔案,利用sqlite3模組(Module)來連接與設定撈取StockNumbers資料表中的StockNo欄位資料SQL指令,如下範例第9~11行:
from datetime import datetime import requests import sqlite3 today = datetime.now().strftime('%Y%m%d') #西元年(yyyymmdd) chinese_today = f"{(datetime.now().year - 1911)}/{datetime.now().strftime('%m/%d')}" #民國年(yyy/mm/dd) conn = sqlite3.connect('Stocks.db') cursor = conn.cursor() cursor.execute('SELECT StockNo FROM StockNumbers') response = requests.get( f'https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date={today}&stockNo=2330') response_data = response.json()['data'] result = [data for index, data in enumerate(response_data) if chinese_today in response_data[index]] if result: #如果有資料 result[0].insert(0, '2330') print(result)
接著,呼叫sqlite3模組(Module)的fetchall()方法(Method),執行撈取StockNo欄位的所有股票代碼資料SQL指令,並且透過迴圈來進行讀取與替換既有的股票代碼,如下範例第13、15、21行:
from datetime import datetime import requests import sqlite3 today = datetime.now().strftime('%Y%m%d') #西元年(yyyymmdd) chinese_today = f"{(datetime.now().year - 1911)}/{datetime.now().strftime('%m/%d')}" #民國年(yyy/mm/dd) conn = sqlite3.connect('Stocks.db') cursor = conn.cursor() cursor.execute('SELECT StockNo FROM StockNumbers') for stock_no in cursor.fetchall(): response = requests.get( f'https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date={today}&stockNo={stock_no[0]}') response_data = response.json()['data'] result = [data for index, data in enumerate(response_data) if chinese_today in response_data[index]] if result: #如果有資料 result[0].insert(0, stock_no[0]) print(result)
最後,為了讓三個股票代碼資料能夠存放在同一個串列(List)中,所以另外定義了combined串列(List),加入Python網頁爬蟲爬取的所有股票代碼資料,如下範例第13、23行:
from datetime import datetime import requests import sqlite3 today = datetime.now().strftime('%Y%m%d') #西元年(yyyymmdd) chinese_today = f"{(datetime.now().year - 1911)}/{datetime.now().strftime('%m/%d')}" #民國年(yyy/mm/dd) conn = sqlite3.connect('Stocks.db') cursor = conn.cursor() cursor.execute('SELECT StockNo FROM StockNumbers') combined = [] #合併結果 for stock_no in cursor.fetchall(): response = requests.get( f'https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date={today}&stockNo={stock_no[0]}') response_data = response.json()['data'] result = [data for index, data in enumerate(response_data) if chinese_today in response_data[index]] if result: #如果有資料 result[0].insert(0, stock_no[0]) combined.append(result[0]) print(combined)
執行結果
[['2330', '110/08/06', '13,994,018', '8,275,142,201', '596.00', '596.00', '588.00', '591.00', '-5.00', '13,742'], ['2409', '110/08/06', '164,723,579', '3,591,785,901', '22.10', '22.10', '21.60', '21.60', '-0.70', '42,887'], ['2382', '110/08/06', '5,748,237', '441,589,670', '76.90', '77.50', '76.20', '77.10', '+0.70', '3,779']]
五、小結
學會了Python網頁爬蟲讀取資料庫的技巧,當未來想要調整關注的股票代碼時,只需要修改資料庫中的資料即可,而無需變動Python網頁爬蟲的程式碼,讓專案更具有彈性,後續如果想要將爬取到的資料存入資料庫,則可以參考[Python爬蟲教學]輕鬆學會Python網頁爬蟲與MySQL資料庫的整合方式或[Pandas教學]快速掌握Pandas套件讀寫SQLite資料庫的重要方法文章。
如果您喜歡我的文章,別忘了在下面訂閱本網站,以及幫我按五下Like(使用Google或Facebook帳號免費註冊),支持我創作教學文章,回饋由LikeCoin基金會出資,完全不會花到錢,感謝大家。
有想要看的教學內容嗎?歡迎利用以下的Google表單讓我知道,將有機會成為教學文章,分享給大家😊
Python學習資源
Python網頁爬蟲推薦課程
Python非同步網頁爬蟲
Python網頁爬蟲應用
Python網頁爬蟲部署
Python網頁爬蟲資料儲存
Python網頁爬蟲技巧
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYqMPD_mPLEileg1IdrsIYhFSWZkYFKYmEnUqWqiqdiJv2XYnkT23CFcXoTN6HBtGCEUylgVoUIVKm6KPRPM_TjcjsSei4lGE_YmZdrWA6Ulw1fp6-o8Cn-bVwr7_FANFoC4tjTe-ak6w-atFYq-a1pipQbZvQzt4wHRNK7tywcSG0dSCnpJpqoMP5wA/s1600/Python%E7%B6%B2%E9%A0%81%E7%88%AC%E8%9F%B2%E5%85%8D%E8%B2%BB%E7%B7%9A%E4%B8%8A%E5%9F%B9%E8%A8%93.png)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-fK9Da5M7X1lSpbZVan4Eo-PunVnQv-YHw3EDahTUhZr5FayVLaCPqrW44W3_xwQQO-gAWZEwe_A-SxL_nltT__ArbFOgLYAAIsi3RzETT9GqVsfyfN9PXDs-xGTkxZSqj_W1SCxwD2UcrJLqHZSYIrLB-HIU75vSom4YoqoWFUQz_o4PbnvTQUbE6Bab/w640-h426/2.png)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg61JC7N1hyphenhyphenPpzb1hNJauunevoWrOsJxk_Upz0ywnLtIAJ2rdd1ZxChyphenhyphenFPq8GHYfywtHv2mTce5NGdwwxWFWYARhA6In0xlOzkwlRb9kM04mwgdy9Un9JgVCoLQnwV25oUcitQy2OY4TeA3gVIs067wR4StGfkldbykOeL3TfPchWfNClWKhL10ZzWaxFtf/w640-h426/3.png)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh1XFQE0AmkZHSFB0Icq3uY4_FdsIYZ9nUqllOlo9ulRu0ri-LS1OeW2ybKOO2QRg-gyUOUr_3sMLYf7S4Q5ULZpIcXsS1pAkSMPm0OwqpbnLET51WEpQ3EoY5WaEVEWyTixBkRqp2tA7SpePM_MCIY6tnyUvu917rulqbLJTEEPsEho6Q-4Tf74DFdakd/w640-h426/4.png)
請問使用json函式之前不用先import json嗎
回覆刪除