上回改版為 v8 時沒有順便處理被預約書的到期日, 收到 Telegram 訊息時只知道哪些書被預約了, 還是要登入網站去查哪一天須還, 挺麻煩的, 今天花了點時間補抓到期日資訊, 改版為 v9.
本爬蟲系列全部測試文章索引參考 :
到期日資訊列在借閱書籍列表的第三欄 :
到期日被包裹在一個 P 元素裡面, 可用 data-qa="automation_mlc_record_date" 屬性定位, 其 XPATH 為 .//p[@data-qa="automation_mlc_record_date"] :
<p data-qa="automation_mlc_record_date" class="normal-text" ...>
<span translate="nui.loan.due">到期</span>:
12/01/2025, 23:59
</p>
只要用正規表達式 r'\d{2}/\d{2}/\d{4}' 就可以將 P 元素中符合日期格式的內容抓出來, 所以需要匯入標準庫中的 re 模組. 完整程式碼如下 :
# nkust_lib_9.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
async def telegram_send_text(text):
bot=Bot(token=token)
try:
await bot.send_message(
chat_id=chat_id,
text=text
)
return True
except Exception as e:
print(f'Error sending text: {e}')
return False
def get_nkust_lib():
try:
options=Options()
options.add_argument("--headless")
driverpath='/usr/lib/chromium-browser/chromedriver'
service=Service(driverpath)
browser=webdriver.Chrome(options=options, service=service)
browser.implicitly_wait(60)
browser.maximize_window()
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')
md_list[1].click()
print('按其他讀者 ... OK')
# 登入系統
login_user_name=browser.find_element(By.ID, 'LoginUserName')
login_user_name.send_keys('我的借書證帳號')
login_password=browser.find_element(By.ID, 'LoginPassword')
login_password.send_keys('借書證密碼')
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) # 等待 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_element(By.CSS_SELECTOR, "h3 a")
title=title_elem.text.strip()
# 2. 取得整個 item 的文字
item_text=item.text.strip()
# 3. 嘗試抓到期日
try:
due_elem=item.find_element(By.XPATH, './/p[@data-qa="automation_mlc_record_date"]')
due_text=due_elem.text.strip()
# 擷取出「12/01/2025」格式之到期日
m=re.search(r'\d{2}/\d{2}/\d{4}', due_text)
due_date=m.group(0) if m else ''
except Exception:
due_date=''
# 4. 判斷借閱狀態是否包含 "已續借"
if "已續借" not in item_text:
unrenew_books.append((title, due_date))
#print(f"[DEBUG] {title} -> {item_text} / 到期日: {due_date}")
except Exception as e:
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:
browser.close()
return msg
if __name__ == '__main__':
start=time.time()
msg=get_nkust_lib()
token='Telegram 權杖'
chat_id='Telegram 聊天室 ID'
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}')
主要的異動部分為抓到期日的藍色字部分 (每一本借閱書籍都會抓), 在步驟四判斷若該書被預約, 則將書名與到期日組成 tuple 放入 unrenew_books 串列裡, 因為從原本的書名字串改成 tuple, 所以組成 msg 字串時 t 是一個 tuple, 要用 t[0] 取出書名, 用 t[1] 取出到期日, 執行結果如下 :
pi@raspberrypi:~ $ python3 nkust_lib_9.py
按其他讀者 ... OK
登入系統 ... OK
按名字顯現選單 ... OK
按我的借閱 ... OK
按全部續借 ... OK
2025-11-11 17:03:32
被預約的書:
1. Python原力爆擊 : OpenAI / Gemini / AWS / Ollama生成式AI應用新手指南 / 柯克(Ko Ko)等著 (c.3) 到期日: 12/02/2025
2. AI應用程式開發 : 活用ChatGPT與LLM技術開發實作 / Olivier Caelen, Marie-Alice Blete著 ; 藍子軒譯 到期日: 12/01/2025
3. Python金融市場賺大錢聖經 : 寫出你的專屬指標 / 張峮瑋作 到期日: 11/15/2025
執行時間:354.4999508857727
收到的 Telegram 訊息 :
最後將 v9 程式添加可執行權限, 並更改 crontab 中定時執行的爬蟲程式為 v9 :
pi@raspberrypi:~ $ chmod +x nkust_lib_9.py
pi@raspberrypi:~ $ ls -ls nkust_lib_9.py
8 -rwxr-xr-x 1 pi pi 6148 11月 12 08:31 nkust_lib_9.py
pi@raspberrypi:~ $ crontab -e
0 6,16 * * * /usr/bin/python3 /home/pi/nkust_lib_9.py
crontab: installing new crontab
終於弄成自己想要的樣子啦, 收工.



沒有留言 :
張貼留言