前陣子發現 Mapleboard 的 Ubuntu Mate 升版後自動新增了預設的 Guest 帳戶, 因為其權限不足以連線網路, 導致主機掛點網站連埠上. 修復此問題後花了近一個月時間來打理架站與主機安全防護. 這兩天完成後想說應該要讓主機每天早上傳送一個訊息 (Email 或 LINE/Telegram 訊息) 給我, 讓我知道系統仍正常運行中才對. 那要傳甚麼呢? 當然, 傳個 "早安" 是再簡單不過了, 但我想弄點較有意思的, 那就傳個名言或格言吧!
1. 撰寫格言爬蟲 :
我找到下面這個免申請帳號與 Key 就能取得格言的網站 :
它提供一個可隨機傳回格言的 API 網址 :
在瀏覽器輸入此 API url 會傳回一個 JSON 字串 :
[ {"q":"Pleasure can be supported by an illusion; but happiness rests upon truth. ","a":"Nicolas Chamfort","h":"<blockquote>“Pleasure can be supported by an illusion; but happiness rests upon truth. ” — <footer>Nicolas Chamfort</footer></blockquote>"} ]
其中 "q" 鍵為格言本身, "a" 鍵為作者, 我們可以用 requests 來取得格言內容 :
>>> import requests
>>> url='https://zenquotes.io/api/random'
>>> res=requests.get(url)
>>> res
<Response [200]>
呼叫 Response 物件的 json() 方法將 JSON 字串轉成字典串列 :
>>> data=res.json()
>>> type(data)
<class 'list'>
>>> len(data)
1
可見此串列只有一個元素 :
>>> data[0]
{'q': 'Experience is a comb which nature gives us when we are bald. ', 'a': 'Chinese Proverb', 'h': '<blockquote>“Experience is a comb which nature gives us when we are bald. ” — <footer>Chinese Proverb</footer></blockquote>'}
>>> data[0]['q']
'Experience is a comb which nature gives us when we are bald. '
>>> data[0]['a']
'Chinese Proverb'
這樣便取得格言內容與作者了, 可以將上面程序寫成 get_quote() 函式 :
>>> def get_quote():
url='https://zenquotes.io/api/random'
try:
res=requests.get(url, timeout=10)
data=res.json()
return data[0]['q'], data[0]['a'] # 成功傳回 (quote, author)
except Exception as e:
return None, f'Failed to fetch quote: {e}' # 失敗傳回 (None, '失敗訊息')
呼叫函式 :
>>> quote, author=get_quote()
>>> quote
'You have to keep breaking your heart until it opens.'
>>> author
'Rumi'
2. 利用 Google Gemini 翻譯格言 :
但我想要同時顯示其中文翻譯 (中英對照), 格式例如 :
快樂可以靠幻想支撐,
但幸福建立在真理之上。
Pleasure can be supported by an illusion;
but happiness rests upon truth.
—— Nicolas Chamfort
中文翻譯可以利用 Google Gemini 大語言模型搭配合適的提示詞來達成, 這必須先申請 Gemini API Key 與安裝 google-generativeai 套件, 作法參考 :
我已有 Gemini API Key, 先存入變數中 :
>>> gemini_api_key='我的 Gemini API Key'
然後匯入 google.generativeai 模組並取簡名 genai :
>>> import google.generativeai as genai
接著呼叫 configure() 函式並傳入 API Key 來認證金鑰 :
>>> genai.configure(api_key=gemini_api_key)
若沒有傳回錯誤訊息那就表示認證成功了, 呼叫 GenerativeModel() 函式並傳入模型名稱來建立模型物件, 考量反應速度我選擇 'gemini-2.0-flash' 模型 :
>>> model=genai.GenerativeModel('gemini-2.0-flash')
然後設計提示詞要求模型依照指示執行翻譯任務 :
>>> prompt=f'請將以下英文翻譯為繁體中文, 只要翻譯一次即可:{quote}'
>>> prompt
'請將以下英文翻譯為繁體中文, 只要翻譯一次即可:You have to keep breaking your heart until it opens.'
最後呼叫模型物件的 generate_content() 方法來生成翻譯 :
>>> reply=model.generate_content(prompt)
回應內容放在回應物件的 text 屬性中 :
>>> reply.text
'你必須不斷讓你的心碎裂,直到它敞開。\n'
將上面程序寫成如下之函式 :
>>> def translate_quote(quote, api_key):
genai.configure(api_key=api_key)
model=genai.GenerativeModel('gemini-2.0-flash')
prompt=f'請將以下英文翻譯為繁體中文, 只要翻譯一次即可:{quote}'
try:
reply=model.generate_content(prompt)
return reply.text.strip().strip('\"\n ') # 清除結尾開頭之雙引號跳行與空格
except Exception as e:
return f'格言翻譯失敗:{e}'
>>> quote_zh_tw=translate_quote(quote, gemini_api_key)
>>> quote_zh_tw
'你必須不斷地讓你的心碎裂,直到它敞開。'
這樣就可以將格言之中英文與作者用 f 字串組成輸出訊息了 :
>>> def bilingual_quote(quote, quote_zh_tw, author):
return f'早安! 今日格言:\n「{quote_zh_tw}」\n{quote}\n—— {author}'
>>> msg=bilingual_quote(quote, quote_zh_tw, author)
>>> msg
'早安! 今日格言:\n「你必須不斷地讓你的心破碎,直到它真正敞開。」\nYou have to keep breaking your heart until it opens.\n—— Rumi'
以上測試的完整程式碼如下 :
# dailly_quote.py
import requests
import google.generativeai as genai
def get_quote():
url='https://zenquotes.io/api/random'
try:
res=requests.get(url, timeout=10)
data=res.json()
return data[0]['q'], data[0]['a'] # 成功傳回 (quote, author)
except Exception as e:
return None, f'Failed to fetch quote: {e}' # 失敗傳回 (None, '失敗訊息')
def translate_quote(quote, api_key):
genai.configure(api_key=api_key)
model=genai.GenerativeModel('gemini-2.0-flash')
prompt=f'請將以下英文翻譯為繁體中文, 只要翻譯一次即可:{quote}'
try:
reply=model.generate_content(prompt)
return reply.text.strip().strip('\"\n ') # 清除結尾開頭之雙引號跳行與空格
except Exception as e:
return f'格言翻譯失敗:{e}'
def bilingual_quote(quote, quote_zh_tw, author):
return f'早安! 今日格言:\n「{quote_zh_tw}」\n{quote}\n—— {author}'
# 取得每日格言與其中文翻譯
quote, author=get_quote()
gemini_api_key='我的 Gemini API Key'
quote_zh_tw=translate_quote(quote, gemini_api_key)
msg=bilingual_quote(quote, quote_zh_tw, author)
print(msg)
執行結果如下 :
>>> %Run dailly_quote.py
早安! 今日格言:
「開始一件事情遠比完成它容易得多。」
It is far easier to start something than it is to finish it.
—— Amelia Earhart
3. 利用 Google SMTP 郵件伺服器傳送每日格言 :
使用 Google SMTP 伺服器傳送郵件的方法參考 :
我取其中 smtp_mail_test_2.py 的 send_mail() 添加主旨 Unicode 處理, 改寫上面的 dailly_quote.py 如下 :
# dailly_quote.py
import requests
import google.generativeai as genai
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
def get_quote():
url='https://zenquotes.io/api/random'
try:
res=requests.get(url, timeout=10)
data=res.json()
return data[0]['q'], data[0]['a'] # 成功傳回 (quote, author)
except Exception as e:
return None, f'Failed to fetch quote: {e}' # 失敗傳回 (None, '失敗訊息')
def translate_quote(quote, api_key):
genai.configure(api_key=api_key)
model=genai.GenerativeModel('gemini-2.0-flash')
prompt=f'請將以下英文翻譯為繁體中文, 只要翻譯一次即可:{quote}'
try:
reply=model.generate_content(prompt)
return reply.text.strip().strip('\"\n ') # 清除結尾開頭之雙引號跳行與空格
except Exception as e:
return f'格言翻譯失敗:{e}'
def bilingual_quote(quote, quote_zh_tw, author):
return f'早安! 今日格言:\n「{quote_zh_tw}」\n{quote}\n—— {author}'
def send_mail(account, password, subject, from_addr, to_addr, cc_addr=None, body=''):
if cc_addr is None:
cc_addr=[] # 預設空串列
# 登入 Google SMTP 伺服器
smtp=smtplib.SMTP('smtp.gmail.com', 587)
smtp.ehlo()
smtp.starttls() # 啟動 TLS 安全傳輸
smtp.login(account, password) # 登入 Google SMTP 伺服器
# 建立郵件內容
content=MIMEMultipart()
content['Subject']=Header(subject, 'utf-8')
content['From']=from_addr
content['To']=', '.join(to_addr)
content['Cc']=', '.join(cc_addr)
# 添加郵件正文
content.attach(MIMEText(body, 'plain', 'utf-8'))
# 合併收件人和副本收件人
all_recipients=to_addr + cc_addr
status=smtp.sendmail(from_addr, all_recipients, content.as_string())
if status == {}:
print('郵件傳送成功!')
else:
print('郵件傳送失敗!')
smtp.quit()
# 取得每日格言與其中文翻譯
quote, author=get_quote()
gemini_api_key='我的 Gemini API Key'
quote_zh_tw=translate_quote(quote, gemini_api_key)
msg=bilingual_quote(quote, quote_zh_tw, author)
# 用 Google SMTP 伺服器傳送信件
account='mygmail@gmail.com' # Gmail 帳號
password='azfkqbjbftodjucd' # Google 應用程式密碼 (這是樣本)
subject='今日格言' # 主旨
from_addr='mygmail@gmail.com' # 寄件人
to_addr=['myhinet@ms5.hinet.net'] # 收件人
cc_addr=[] # 副本
body=msg # 信件內容
send_mail(account, password, subject, from_addr, to_addr, cc_addr, body)
結果如下 :
>>> %Run dailly_quote.py
郵件傳送成功!


沒有留言 :
張貼留言