之前版本的爬蟲我都把帳號密碼金鑰等等都寫在程式碼裡, 這實在不是好的做法, 今天將爬蟲進行改版, 將帳密金鑰都存放在隱藏檔 .env 中, 於程式裡利用 dotenv 從 .env 檔讀取出來. 關於 dotenv 用法參考 :
本系列全部文章索引參考 :
先將目前的第 10 版爬蟲複製一份到第 11 版 :
pi@kaopi3:~ $ cp nkust_lib_10.py nkust_lib_11.py
用 nano 編輯程式碼 :
pi@kaopi3:~ $ nano nkust_lib_11.py
修改為如下 :
# nkust_lib_11.py
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
import time
import requests
from datetime import datetime
import asyncio
from telegram import Bot
import re
from dotenv import dotenv_values
async def telegram_send_text(text):
bot=Bot(token=TELEGRAM_TOKEN)
try:
await bot.send_message(
chat_id=TELEGRAM_ID,
text=text
)
return True
except Exception as e:
print(f'Error sending text: {e}')
return False
def get_nkust_lib():
browser=None
msg="無法取得資料" # ✅ 防止未賦值
try:
options=Options()
options.add_argument("--headless=new")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.binary_location="/usr/bin/chromium"
service=Service("/usr/bin/chromedriver")
browser=webdriver.Chrome(service=service, options=options)
browser.implicitly_wait(60)
browser.set_window_size(1920, 1080)
url=(
'https://nkust.primo.exlibrisgroup.com/discovery/login?'
'vid=886NKUST_INST:86NKUST&lang=zh-tw'
)
browser.get(url)
# 按其他讀者
md_list=browser.find_elements(By.TAG_NAME, 'md-list-item')
if len(md_list) > 1:
md_list[1].click()
print('按其他讀者 ... OK')
# 登入系統
login_user_name=browser.find_element(By.ID, 'LoginUserName')
login_user_name.send_keys(NKUST_LIB_ID)
login_password=browser.find_element(By.ID, 'LoginPassword')
login_password.send_keys(NKUST_LIB_PWD)
login_btn=browser.find_element(By.CLASS_NAME, 'button-large')
login_btn.click()
print('登入系統 ... OK')
# 按名字顯現選單
user_btn=browser.find_element(By.CLASS_NAME, 'user-button')
actions=ActionChains(browser)
actions.move_to_element(user_btn)
actions.click(user_btn)
actions.perform()
print('按名字顯現選單 ... OK')
# 按我的借閱鈕
xpath='/html/body/div[3]/md-menu-content/md-menu-item[3]/button'
my_borrow=browser.find_element(By.XPATH, xpath)
actions.move_to_element(my_borrow)
actions.click(my_borrow)
actions.perform()
print('按我的借閱 ... OK')
# 按全部續借
xpath=(
'/html/body/primo-explore/div/prm-account/md-content'
'/div[2]/prm-account-overview/md-content/md-tabs/'
'md-tabs-content-wrapper/md-tab-content[2]/div/'
'div/prm-loans/div[1]/div[2]/div[2]/button'
)
all_borrow=browser.find_element(By.XPATH, xpath)
actions.move_to_element(all_borrow)
actions.click(all_borrow)
actions.perform()
print('按全部續借 ... OK')
# 檢查續借結果
xpath=(
'/html/body/primo-explore/div/prm-account/md-content'
'/div[2]/prm-account-overview/md-content/md-tabs'
'/md-tabs-content-wrapper/md-tab-content[2]/div/div'
'/prm-loans/div[2]/prm-alert-bar/div/div/span'
)
alert_span=browser.find_element(By.XPATH, xpath)
if '所有借閱資料已成功續借' in alert_span.text:
msg='❖ 所有借閱資料已成功續借'
else:
msg='❖ 只有部分借閱資料已成功續借'
# 檢查是否有 "載入更多結果" 按鈕
for i in range(3): # 最多 3 頁
load_more=browser.find_elements(By.CLASS_NAME, 'button-confirm')
if not load_more:
break
load_more[0].click()
time.sleep(2)
# 抓取所有借閱書目
loan_items=browser.find_elements(By.TAG_NAME, 'md-list-item')
unrenew_books=[]
for item in loan_items:
try:
# ✅ 1. 必須有書名才是書
title_elem=item.find_elements(By.CSS_SELECTOR, "h3 a")
if not title_elem:
continue
title=title_elem[0].text.strip()
item_text=item.text.strip()
# ✅ 2. 取得到期日
due_text=''
due_elem=item.find_elements(By.XPATH, './/p[@data-qa="automation_mlc_record_date"]')
if due_elem:
m=re.search(r'\d{2}/\d{2}/\d{4}', due_elem[0].text)
if m:
due_text=m.group(0)
# ✅ 3. 只收真正「被預約 / 無法續借」
if any(k in item_text for k in ["被預約", "無法續借", "recall"]):
unrenew_books.append((title, due_text))
except Exception:
continue
if unrenew_books:
msg="被預約的書:\n" + "\n".join(
[f"{i+1:>2}. {t[0]} 到期日: {t[1]}" for i, t in enumerate(unrenew_books)]
)
else:
msg="全部書籍皆已續借"
print('搜尋被預約書籍 ... OK')
except Exception as e:
print(e)
finally:
if browser:
browser.quit() # ✅ 防呆
return msg # ✅ msg 一定有值
if __name__ == '__main__':
start=time.time()
config=dotenv_values('.env')
NKUST_LIB_ID=config.get('NKUST_LIB_ID')
NKUST_LIB_PWD=config.get('NKUST_LIB_PWD')
TELEGRAM_TOKEN=config.get('TELEGRAM_TOKEN')
TELEGRAM_ID=config.get('TELEGRAM_ID')
#print(NKUST_LIB_ID)
#print(NKUST_LIB_PWD)
#print(TELEGRAM_TOKEN)
#print(TELEGRAM_ID)
msg=get_nkust_lib()
if msg:
now=datetime.now().strftime('%Y-%m-%d %H:%M:%S')
msg='\n' + now + '\n' + msg
if asyncio.run(telegram_send_text(msg)):
print('訊息傳送成功!')
else:
print('訊息傳送失敗!')
print(msg)
end=time.time()
print(f'執行時間:{end-start}')
黃底高亮者為修改或添加的部分, 執行結果如下 :
pi@kaopi3:~ $ python nkust_lib_11.py
按其他讀者 ... OK
登入系統 ... OK
按名字顯現選單 ... OK
按我的借閱 ... OK
按全部續借 ... OK
訊息傳送成功!
2026-04-18 00:37:52
❖ 所有借閱資料已成功續借
執行時間:81.74577593803406






