由於前一篇內容太長了, 所以用 Line Notify 推播所爬取的科技新聞改記在此篇, 本系列前一篇文章參考 :
Line Notify 的用法參考 :
一. Line Notify 函式 :
Line Notify 的語法很制式, 可以寫成下列函式來方便呼叫 :
import requests
def line_notify(msg, token):
url="https://notify-api.line.me/api/notify"
headers={"Authorization": "Bearer " + token,
"Content-Type": "application/x-www-form-urlencoded"
}
payload={"message": msg}
r=requests.post(url, headers=headers, params=payload)
return r.status_code
此函式使用第三方模組 requests 傳送 HTTP POST 方法給 Line Notify 伺服器.
二. 科技新聞網站爬蟲函式 :
參考前一篇測試記錄, 將爬蟲程式寫成函式 :
注意, 只要爬今日新聞即可, 因為經過測試, 發現爬近一周新聞訊息會過長, 會超過 Line Notify 的限制 (每則訊息不可以超過 1000 個字元) 而導致訊息傳送失敗.
今日新聞的爬蟲函式如下 :
def get_today_news(tn): # tn=科技新聞網站名稱, 例如 'ithome'
msg=[] # 儲存新聞訊息
news=TechNews(tn) # 建立物件
try: # 捕捉爬蟲套件無法載入頁面例外
today_news=news.get_today_news() # 取得今日新聞
time.sleep(5) # 等候爬蟲取得新聞
if today_news['news_counts'] > 0: # 有新聞才製作回傳訊息
msg.append(f'@ {tn} ({technews[tn]})') # 訊息標題
news_contents=today_news['news_contents'] # 取得全部新聞內容
the_date='' # 記錄新聞日期
for key in news_contents: # 拜訪各新聞條目
contents=news_contents[key] # 取得新聞內容
title=f'❖ {contents["title"]}' # 新聞標題
msg.append(title) # 加入訊息串 list
msg.append(f'▶ {contents["link"]}') # 將連結加入訊息串 list
the_date=contents["date"] # 更新新聞日期
msg.insert(0, f'\n今日科技新聞 ({the_date})') # 標題含日期 (開頭須跳 1 行)
except Exception as e:
print(e)
return '\n'.join(msg) # 以跳行串接訊息串 list 為字串後傳回
此函式針對傳入的新聞網站名稱取得其新聞內容, 然後用迴圈將新聞逐條放入串列中, 最後用跳行串接成一個字串傳回.
三. 發行 Line Notify 存取權杖 :
要推送 Line Notify 訊息必須先取得其伺服器之存取權杖, 作法參考 :
先用手機 Line 帳號登入 Line Notify 網站 :
登入成功後按按右上角帳號名稱, 點選 "個人頁面" :
拉到頁面底部按 "發行權杖" 鈕 :
在彈出視窗中填寫訊息標題, 並點選要推送的群組 (也可以選一對一) 後按發行 :
這時會顯示發行之權杖, 請先按左邊的 "複製" 將權杖貼到文字檔中保存 :
四. 佈署爬蟲程式 :
取得權杖後就可以將上面函式整合成完整的爬蟲程式如下 :
# technews_1.py
import time
import requests
from technews import TechNews
def line_notify(msg, token):
url="https://notify-api.line.me/api/notify"
headers={"Authorization": "Bearer " + token,
"Content-Type": "application/x-www-form-urlencoded"
}
payload={"message": msg}
r=requests.post(url, headers=headers, params=payload)
return r.status_code
def get_today_news(tn):
msg=[]
news=TechNews(tn)
try:
today_news=news.get_today_news()
time.sleep(5)
if today_news['news_counts'] > 0:
msg.append(f'@ {tn} ({technews[tn]})')
news_contents=today_news['news_contents']
the_date=''
for key in news_contents:
contents=news_contents[key]
title=f'❖ {contents["title"]}'
msg.append(title)
msg.append(f'▶ {contents["link"]}')
the_date=contents["date"]
msg.insert(0, f'\n今日科技新聞 ({the_date})')
except Exception as e:
print(e)
return '\n'.join(msg)
if __name__ == '__main__':
technews={'ithome': '電腦報',
'business': '數位時代',
'inside': '硬塞的'}
msg=[]
for tn in technews:
msg=get_today_news(tn)
print(msg)
print(f'訊息長度={len(msg)} 字元')
if len(msg):
token='ud7PaDL45fz849A0e1f5oaMCbRIkxMXapQCt7PfNkzz' # 此為範例權杖
code=line_notify(msg, token)
if code==200:
print('Line 訊息發送成功!')
else:
print(f'Line 訊息發送失敗! (code={code})')
else:
print(f'{technews[tn]} ({tn}) 無資料')
由於將三個網站新聞一次送給 Line Notify 伺服器訊息長度會超過限制, 導致訊息傳送失敗 (code=400), 因此最好是每個網站傳送一則訊息, 不要全部擠在一起送, 關於 Line Notify 的回傳碼說明參考 :
此程式將三個科技新聞網站名稱做成字典, 然後用迴圈一一去呼叫 get_today_news() 爬新聞, 將取得之各條新聞內容串成字串後傳回. 因為每則新聞日期都是同一天, 因此在迭代每則新聞時會持續記錄日期 (其實都是同一日期), 迭代完再將日期與推播標題插入 msg 串列的最前面.
執行結果如下 :
測試 OK 後把此 technews_1.py 程式上傳到高雄家裡的那台樹莓派 Pi 3, 把其中 print(msg) 註解掉後存檔, 但此 Python 程式檔預設並無可執行權限 :
pi@raspberrypi:~ $ ls -ls technews_1.py
4 -rw-r--r-- 1 pi pi 1786 3月 25 23:56 technews_1.py
可用 chmod 指令更改權限為可執行 :
pi@raspberrypi:~ $ sudo chmod +x /home/pi/technews_1.py
pi@raspberrypi:~ $ ls -ls technews_1.py
4 -rwxr-xr-x 1 pi pi 1786 3月 25 23:56 technews_1.py
接著編輯 Crontab 添加自動執行此程式的時間 :
pi@raspberrypi:~ $ crontab -e
加入一筆定時執行設定 :
0 9,17 * * * /usr/bin/python3 /home/pi/technews_1.py
這是設定每天 09:00 與 17:00 執行此程式一次 :
編輯完按 Ctrl+O 存檔, 再按 Ctrl+X 關閉檔案即可. 可用 crontab -l 顯示 crontab 目前設定 :
pi@raspberrypi:~ $ crontab -l
0 16 * * 1-5 /usr/bin/python3 /home/pi/twstock_dashboard_update.py
*/31 9-13 * * 1-5 /usr/bin/python3 /home/pi/yahoo_twstock_monitor_table.py
0 8,18 * * * /usr/bin/python3 /home/pi/btc_eth_prices_line_notify.py
0 9,17 * * * /usr/bin/python3 /home/pi/technews_1.py
參考 :
# 各類符號表
沒有留言:
張貼留言