跳到主要內容

[Python爬蟲教學]活用openpyxl套件將爬取的資料寫入Excel檔案

python_write_to_an_excel_file_using_openpyxl_module
Photo by UX Indonesia on Unsplash

在開發Python網頁爬蟲時,除了可以將取得的資料儲存在資料庫外,有時候,也會想要匯出成Excel檔案,進而使用其中的圖形化功能,來製作統計圖表,有效率的進行資料分析。

所以本文延續[Python爬蟲教學]輕鬆學會Python網頁爬蟲與MySQL資料庫的整合方式文章,整合Pythonopenpyxl套件,將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原始碼為:

python_write_to_an_excel_file_using_openpyxl_module
由於標題只需爬取一次,放置於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檔案,如下圖:

python_write_to_an_excel_file_using_openpyxl_module

開啟yahoostock.xlsx檔案,即可看到執行結果,如下圖:

python_write_to_an_excel_file_using_openpyxl_module

三、整合openpyxl套件客製化顯示資料

成功將爬取的股票當日行情資料匯出成Excel檔案,您可能會想要在漲跌的欄位,使用顏色來進行區別,這時候,就可以增加引用openpyxlFont模組(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),所以在迴圈的地方,需搭配使用Pythonenumerate()方法(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_write_to_an_excel_file_using_openpyxl_module

四、小結

本文在Python網頁爬蟲的專案中,整合了openpyxl套件,將爬取的股票當日行情資料,匯出成Excel檔案,並且客製化儲存格文字顯示方式,來幫助使用者檢視資料,後續就能夠使用Excel檔案的圖形化功能,快速建立所需的分析報表。大家也來練習使用openpyxl套件,將爬取的資料匯出成Excel檔案吧~

如果您喜歡我的文章,請幫我按五下Like(使用GoogleFacebook帳號免費註冊),支持我創作教學文章,回饋由LikeCoin基金會出資,完全不會花到錢,感謝大家。

有想要看的教學內容嗎?歡迎利用以下的Google表單讓我知道,將有機會成為教學文章,分享給大家😊

Python學習資源
Python網頁爬蟲推薦課程
    Python網頁爬蟲-BeautifulSoup教學
    Python網頁爬蟲-Selenium教學
    Python非同步網頁爬蟲
    Python網頁爬蟲應用
    Python網頁爬蟲部署
    Python網頁爬蟲資料儲存
    Python網頁爬蟲技巧








    留言

    1. 可以順便分享怎麼將資料存到google sheet嗎?感謝

      回覆刪除
      回覆
      1. 已分享到部落格中囉,網址如下:https://www.learncodewithmike.com/2020/08/python-write-to-google-sheet.html

        刪除
    2. 作者已經移除這則留言。

      回覆刪除
    3. stock = Stock('2451', '2454', '2369') # 建立Stock物件

      Stock都無法被證明,這是甚麼原因呢?

      回覆刪除
      回覆
      1. mark您好:
        「Stock都無法被證明」是執行時出現什麼樣的錯誤訊息嗎?

        刪除
    4. 1 stock = Stock('2451', '2454', '2369') # 建立Stock物件
      ----> 2 stock.export(stock.scrape()) #將爬取的結果匯出成Excel檔案

      AttributeError: 'Stock' object has no attribute 'export'

      這邊怎麼解決? 謝謝。

      回覆刪除
      回覆
      1. TM您好:
        請檢查Stock類別中是否有定義export()方法(Method),可以參考文章中所附的Github專案程式碼,如果還是無法解決,歡迎將程式碼截圖,到Learn Code With Mike粉絲專頁私訊我,將會協助您解決,謝謝 :)

        刪除
    5. 您好:
      想要請問那個三角形符的漲跌號要如何抓下來呢?

      回覆刪除

    張貼留言