在開發Python網頁爬蟲時,除了可以將取得的資料儲存在資料庫外,有時候,也會想要匯出成Excel檔案,進而使用其中的圖形化功能,來製作統計圖表,有效率的進行資料分析。
所以本文延續[Python爬蟲教學]輕鬆學會Python網頁爬蟲與MySQL資料庫的整合方式文章,整合Python的openpyxl套件,將Python網頁爬蟲所取得的股票當日行情資料,匯出成Excel檔案,並且利用openpyxl套件的Font模組(Module),來客製化顯示儲存格的文字顏色,讓使用者對於股票的漲跌一目瞭然,其中實作的重點如下:
- 安裝openpyxl套件
- 整合openpyxl套件匯出爬取的網頁資料
- 整合openpyxl套件客製化顯示資料
一、安裝openpyxl套件
openpyxl是一個Python套件,可以用來讀寫Excel檔案的資料,使用的方式好上手,並且非常直覺,所以本文才會選擇使用openpyxl套件,示範如何將Python網頁爬蟲取得的資料寫入Excel檔案中。
首先,開啟[Python爬蟲教學]輕鬆學會Python網頁爬蟲與MySQL資料庫的整合方式文章的Python網頁爬蟲專案,本文使用Visual Studio Code為例,在Termianl視窗中,利用以下的指令來進行openpyxl套件的安裝:
$ pip install openpyxl
二、整合openpyxl套件匯出爬取的網頁資料
完成安裝後,接下來就要利用openpyxl套件,建立Excel檔案的sheet(工作表),並且利用迴圈,將Python網頁爬蟲取得的股票當日行情資料寫入。
開啟scraper.py檔案,引入openpyxl模組(Module),如下範例:
import openpyxl
接著新增export()方法(Method),包含一個stocks參數,用來接收要匯出的股票當日行情資料,然後,在export()方法(Method)中,建立Excel Workbook(工作簿)物件,事實上就是建立Excel檔案的意思,如下範例:
def export(self, stocks):
wb = openpyxl.Workbook()
有了Workbook(工作簿)後,想像一下,接下來就要新增一個新的sheet(工作表),將它命名為「Yahoo股市」,並且放置於sheet(工作表)中的第一順位,來存放Python網頁爬蟲的資料,這些動作,可以利用openpyxl模組(Module)的create_sheet()方法(Method)來完成,如下範例:
def export(self, stocks):
wb = openpyxl.Workbook()
sheet = wb.create_sheet("Yahoo股市", 0)
通常sheet(工作表)的第一列(row)都為標題,除了可以一欄一欄自行輸入外,也可以利用Python網頁爬蟲,取得Yahoo奇摩股市當日行情資料表格(table)的標題,寫入Excel檔案的第一列(row),來建立標題。
而當日行情資料表格(table)的標題結構,可以在網頁中點擊右鍵,選擇「檢查」,看到它的HTML原始碼為:
由於標題只需爬取一次,放置於Excel檔案的第一列,所以可以挑選其中一支股票代號,爬取標題文字,如下範例:def export(self, stocks): wb = openpyxl.Workbook() sheet = wb.create_sheet("Yahoo股市", 0) response = requests.get( "https://tw.stock.yahoo.com/q/q?s=2451") soup = BeautifulSoup(response.text, "lxml") tables = soup.find_all("table")[2] ths = tables.find_all("th")[0:11]
範例中,利用requests套件取得網頁的回應結果後,使用支援BeautifulSoup套件的lxml解析器來進行解析,接著,第9行透過find_all()方法(Method),定位所有的表格(table)元素,並且只取得第三個表格(table),這時候,就能夠定位這個表格(table)元素下的前11個標題元素(th),如上面範例的第10行。
而要取得這11個標題元素(th)中的文字,就需要利用迴圈進行讀取,並且使用getText()方法(Method)來取得。這邊使用Python Comprehension語法來撰寫,如下範例第11行:
def export(self, stocks): wb = openpyxl.Workbook() sheet = wb.create_sheet("Yahoo股市", 0) response = requests.get( "https://tw.stock.yahoo.com/q/q?s=2451") soup = BeautifulSoup(response.text, "lxml") tables = soup.find_all("table")[2] ths = tables.find_all("th")[0:11] titles = ("資料日期",) + tuple(th.getText() for th in ths) sheet.append(titles)
由於寫入資料到Excel時,資料需要使用串列(List)或元組(Tuple)來進行打包,所以範例中將取得的標題文字利用tuple()方法(Method)打包為元組(Tuple),而前方增加的「資料日期」元組(Tuple),純粹是想要在寫入Excel檔案時,在標題欄位中額外增加「資料日期」的欄位。最後,使用openpyxl模組(Module)的append()方法(Method),寫入Excel檔案。
接下來,就要處理股票當日行情資料的部分,先來回顧一下[Python爬蟲教學]輕鬆學會Python網頁爬蟲與MySQL資料庫的整合方式文章,在scraper.py檔案中建立的scrape()方法(Method)回傳結果,如下範例:
[
('109/08/14', '2451創見', '14:30', '64.7', '64.7', '64.8', '▽0.3', '740', '65.0', '64.9', '64.9', '64.6'),
('109/08/14', '2454聯發科', '14:30', '680', '679', '680', '▽4', '9,654', '684', '670', '683', '670'),
('109/08/14', '2369菱生', '14:30', '11.70', '11.70', '11.75', '△0.20', '3,739', '11.50', '11.50', '11.90', '11.45')
]
可以看到資料結構為一個串列(List),其中包含了每一支股票的當日行情資料元組(Tuple),所以,傳入本文所建立的export()方法(Method)後,就能夠利用迴圈進行讀取,然後,使用openpyxl模組(Module)的append()方法(Method),將每一支股票的當日行情資料元組(Tuple),寫入Excel檔案中,如下範例:
def export(self, stocks): wb = openpyxl.Workbook() sheet = wb.create_sheet("Yahoo股市", 0) response = requests.get( "https://tw.stock.yahoo.com/q/q?s=2451") soup = BeautifulSoup(response.text, "lxml") tables = soup.find_all("table")[2] ths = tables.find_all("th")[0:11] titles = ("資料日期",) + tuple(th.getText() for th in ths) sheet.append(titles) for stock in stocks: sheet.append(stock)
資料寫入完成後,儲存檔案的方式,就是使用openpyxl模組(Module)的save()方法(Method),傳入Excel檔案的名稱,如下範例:
def export(self, stocks): wb = openpyxl.Workbook() sheet = wb.create_sheet("Yahoo股市", 0) response = requests.get( "https://tw.stock.yahoo.com/q/q?s=2451") soup = BeautifulSoup(response.text, "lxml") tables = soup.find_all("table")[2] ths = tables.find_all("th")[0:11] titles = ("資料日期",) + tuple(th.getText() for th in ths) sheet.append(titles) for stock in stocks: sheet.append(stock) wb.save("yahoostock.xlsx")
export()方法(Method)建立完成,就可以利下以下的範例來進行呼叫:
stock = Stock('2451', '2454', '2369') # 建立Stock物件 stock.export(stock.scrape()) #將爬取的結果匯出成Excel檔案
執行後,在專案的資料夾中,就會產生一個Excel檔案,如下圖:
開啟yahoostock.xlsx檔案,即可看到執行結果,如下圖:
三、整合openpyxl套件客製化顯示資料
成功將爬取的股票當日行情資料匯出成Excel檔案,您可能會想要在漲跌的欄位,使用顏色來進行區別,這時候,就可以增加引用openpyxl的Font模組(Module),來客製化儲存格的文字顯示,如下範例:
from openpyxl.styles import Font
接下來,就要判斷每一支股票的當日行情資料,如果第六個資料含有「△」符號,顯示紅色,反之,如果含有「▽」符號,則顯示綠色,如下範例:
def export(self, stocks): wb = openpyxl.Workbook() sheet = wb.create_sheet("Yahoo股市", 0) response = requests.get( "https://tw.stock.yahoo.com/q/q?s=2451") soup = BeautifulSoup(response.text, "lxml") tables = soup.find_all("table")[2] ths = tables.find_all("th")[0:11] titles = ("資料日期",) + tuple(th.getText() for th in ths) sheet.append(titles) for stock in stocks: sheet.append(stock) if "△" in stock[6]: #儲存格字體顯示紅色 elif "▽" in stock[6]: #儲存格字體顯示綠色 wb.save("yahoostock.xlsx")
由於在存取Excel檔案的儲存格時,會使用到索引值(index),所以在迴圈的地方,需搭配使用Python的enumerate()方法(Method)及Unpacking技巧,詳細的觀念可以參考[Python教學]Python Unpacking實用技巧分享文章,如下範例第14行:
def export(self, stocks): wb = openpyxl.Workbook() sheet = wb.create_sheet("Yahoo股市", 0) response = requests.get( "https://tw.stock.yahoo.com/q/q?s=2451") soup = BeautifulSoup(response.text, "lxml") tables = soup.find_all("table")[2] ths = tables.find_all("th")[0:11] titles = ("資料日期",) + tuple(th.getText() for th in ths) sheet.append(titles) for index, stock in enumerate(stocks): sheet.append(stock) if "△" in stock[6]: #儲存格字體顯示紅色 elif "▽" in stock[6]: #儲存格字體顯示綠色 wb.save("yahoostock.xlsx")
迴圈的索引值(index)要特別注意是從0開始,而Excel檔案中的股票當日行情資料是從第2列(row)開始寫入,所以在存取Excel檔案的儲存格時,列(row)的部分需要加2,欄(column)則固定為第7欄(漲跌),如下範例:
def export(self, stocks): wb = openpyxl.Workbook() sheet = wb.create_sheet("Yahoo股市", 0) response = requests.get( "https://tw.stock.yahoo.com/q/q?s=2451") soup = BeautifulSoup(response.text, "lxml") tables = soup.find_all("table")[2] ths = tables.find_all("th")[0:11] titles = ("資料日期",) + tuple(th.getText() for th in ths) sheet.append(titles) for index, stock in enumerate(stocks): sheet.append(stock) if "△" in stock[6]: sheet.cell(row=index+2, column=7).font = Font(color='FF0000') #儲存格字體顯示紅色 elif "▽" in stock[6]: sheet.cell(row=index+2, column=7).font = Font(color='00A600') #儲存格字體顯示綠色 wb.save("yahoostock.xlsx")
範例中,第15行使用openpyxl模組(Module)的append()方法(Method)將股票當日行情資料寫入後,接著在判斷式中利用cell()方法(Method)來定位儲存格,在列(row)的地方,將每次的迴圈索引值(index)加2,而欄(column)則固定於第7欄(漲跌)。然後,利用openpyxl套件的Font模組(Module),來設定儲存格的文字顏色。執行結果如下:
四、小結
本文在Python網頁爬蟲的專案中,整合了openpyxl套件,將爬取的股票當日行情資料,匯出成Excel檔案,並且客製化儲存格的文字顯示方式,來幫助使用者檢視資料,後續就能夠使用Excel檔案的圖形化功能,快速建立所需的分析報表。大家也來練習使用openpyxl套件,將爬取的資料匯出成Excel檔案吧~
可以順便分享怎麼將資料存到google sheet嗎?感謝
回覆刪除已分享到部落格中囉,網址如下:https://www.learncodewithmike.com/2020/08/python-write-to-google-sheet.html
刪除作者已經移除這則留言。
回覆刪除stock = Stock('2451', '2454', '2369') # 建立Stock物件
回覆刪除Stock都無法被證明,這是甚麼原因呢?
mark您好:
刪除「Stock都無法被證明」是執行時出現什麼樣的錯誤訊息嗎?
1 stock = Stock('2451', '2454', '2369') # 建立Stock物件
回覆刪除----> 2 stock.export(stock.scrape()) #將爬取的結果匯出成Excel檔案
AttributeError: 'Stock' object has no attribute 'export'
這邊怎麼解決? 謝謝。
TM您好:
刪除請檢查Stock類別中是否有定義export()方法(Method),可以參考文章中所附的Github專案程式碼,如果還是無法解決,歡迎將程式碼截圖,到Learn Code With Mike粉絲專頁私訊我,將會協助您解決,謝謝 :)
您好:
回覆刪除想要請問那個三角形符的漲跌號要如何抓下來呢?