2024年3月25日 星期一

Python 學習筆記 : 用 technews-tw 爬台灣科技新聞網站 (二)

由於前一篇內容太長了, 所以用 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

參考 : 


沒有留言:

張貼留言