# Python 爬蟲結合 LINE Notify 推播591租屋網資訊 ###### tags: `Python` `LINE Notify` `GitHub` `Heroku` ## 緣起 感謝[超簡單一鍵推播 591 租屋資訊完全免 Coding-透過 Google Sheet 與 LINE Notify](https://ithelp.ithome.com.tw/articles/10255573)這篇文章,讓我有靈感及動力嘗試做一個LINE推播! 也很剛好租屋也快到期,但總是會忘記或懶得每天上591看有沒有合適的房子,於是專屬於我需求的LINE Notify通知就此誕生。 一直以來都很想寫些技術文章,或是將自己的筆記整理成一篇文章,剛好也透過這次來練練手。 ## 目標 1. 抓取591租屋網符合條件且為3小時內更新的資訊 2. 每三小時執行一次程式,並透過LINE Notify推播更新的資訊 ## 建置環境 - Python 3.9.2 - GitHub - Heroku ## 申請 LINE Notify 權杖 [LINE Notify](https://notify-bot.line.me/zh_TW/)是LINE官方的帳號,只要與其他網路服務完成連動設定,就可透過LINE Notify發送訊息。 登入後,進入個人頁面。 ![登入頁面](https://i.imgur.com/mt0g5kN.png) 點選發行權杖。 ![發行權杖](https://i.imgur.com/1WrBEaT.png) 填寫LINE Notify名稱及要連動的群組或選擇透過一對一聊天發送,完成後點選發行。 <span style="color:#B5495B">如果是與群組連動,記得要將LINE Notify邀請至群組。</span> ![輸入資料](https://i.imgur.com/ARuoCDM.png) 發行成功,會給你一串權杖,將這串權杖記錄起來。 ![獲得權杖](https://i.imgur.com/lkDsoF5.png) 連動成功,如果有 LINE Notify 的好友,LINE會通知連動設定完成。 ![LINE通知連動成功](https://i.imgur.com/hSGXXp4.png) 成功連動的服務,可於個人頁面**已連動的服務**察看到 ![連動成功頁面](https://i.imgur.com/uRrAaL1.png) ## Python 爬蟲 LINE Notify設定好之後,就開始爬蟲吧! 目標:爬取591租屋資訊! 進入[591租屋](https://rent.591.com.tw/?kind=0&region=8)頁面,依照自己需求設定條件。 ![591網頁](https://i.imgur.com/2ikZ5Ih.png) F12 開啟開發者工具,到 Network 頁籤,找到想要爬取的頁面。 ![F12](https://i.imgur.com/D589Etp.png) 從 Headers 頁籤查看要抓取的 Url 及 Request Haders。 ![Headers](https://i.imgur.com/DB9FDjB.png) 利用 Request 套件建立HTTP請求。 ```` Python # 取得591租屋資訊 import requests #要抓取頁面的Url url = "https://rent.591.com.tw/?kind=0&region=8&section=98,102,101,99,100&rentprice=0,15000&pattern=2&order=posttime&orderType=desc" #自訂 Request Headers headers = { "Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Accept-Encoding" : "gzip, deflate, br", "Accept-Language" : "zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7", "Connection" : "keep-alive", "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36", "Upgrade-Insecure-Requests" : "1", "Cache-Control" : "max-age=0", "Host" : "rent.591.com.tw", "Cookie" : "urlJumpIp=8; urlJumpIpByTxt=%E5%8F%B0%E4%B8%AD%E5%B8%82; is_new_index=1; is_new_index_redirect=1; T591_TOKEN=0mgp6gnmca0m1aes0a653qpk76; _ga=GA1.3.1853129893.1614755590; tw591__privacy_agree=0; _ga=GA1.4.1853129893.1614755590; _fbp=fb.2.1614755592267.503379817; new_rent_list_kind_test=0; _gid=GA1.3.990458239.1615170698; _gid=GA1.4.990458239.1615170698; webp=1; PHPSESSID=ugspv0rqvnetihun53ane0jlc4; XSRF-TOKEN=eyJpdiI6ImloZzR5Qm9SRk1XNVd4bmJ2VG8zNUE9PSIsInZhbHVlIjoiSExCSnRITEZjSE8rWktjVEptSnlEd1AxNEs1cHRcL1dEYktOR0dvUUNwdU9vNVVPUHlaK3UyXC9pOWpCVElxV0JJdzZGWFF0bytcL3MrSGNGSlpyQk96OGc9PSIsIm1hYyI6IjQ5NDgzZjc1YWExYTkyZDQ2YWRjZWQwZDI5YTIwODZhMTJkYzNlMmZiYzUwNmZmMzY2YjNhZjQ4NGI4OGY2NjMifQ%3D%3D; 591_new_session=eyJpdiI6ImpYUE9QWDJWYVwvaVlJc3dUK0ZiY3h3PT0iLCJ2YWx1ZSI6ImVMYnpSQ2ZhNG9VZHNSdWZNMjZTSG5nUTZOaWZlZ05kQkRXVkNLZDAxQlBqWWJneXVZbXZEWmd6SVRrMU5ZbGtrOU9tVG9RZm1CM2ZKUnNYQVlJaTNRPT0iLCJtYWMiOiIwN2UzODgzYWE0OGM2YTlkMDI1YTVjYjkzNmUyYWJiMzA5M2JmN2M0M2Q4NDQ1ODhlYTZkM2E3NzFkMjVjMWZlIn0%3D" } response = requests.get(url=url, headers=headers) print(response) #### 產生結果 #### <Response [200]> #### Response Status Code 200,代表成功 ```` 引用 BeautifulSoup 傳入回傳的HTML。 ```` Python from bs4 import BeautifulSoup soup = BeautifulSoup(response.text, "html.parser") # 輸出排版後的HTML print(soup.prettify()) ```` 執行結果片段 ``` html <div class="sub-nav-list nav-wide"> <dl> <dt> 待租房源 </dt> <dd> <a google-data-stat="頭部導航_租屋_所有房源" href="//rent.591.com.tw"> 所有房源 </a> <a google-data-stat="頭部導航_租屋_房東出租" href="//rent.591.com.tw?shType=host"> 房東出租 </a> <a google-data-stat="頭部導航_租屋_整層住家" href="//rent.591.com.tw?kind=1"> 整層住家 </a> <a google-data-stat="頭部導航_租屋_地圖找房" href="//rent.591.com.tw/map-index.html"> 地圖找房 </a> <a google-data-stat="頭部導航_租屋_獨立套房" href="//rent.591.com.tw?kind=2"> 獨立套房 </a> <a google-data-stat="頭部導航_租屋_捷運找房" href="//rent.591.com.tw?mrt=1"> 捷運找房 </a> <a google-data-stat="頭部導航_租屋_分租套房" href="//rent.591.com.tw?kind=3"> 分租套房 </a> <a google-data-stat="頭部導航_租屋_學校找房" href="//rent.591.com.tw?school=0"> 學校找房 </a> <a google-data-stat="頭部導航_租屋_雅房" href="//rent.591.com.tw?kind=4"> 雅房 </a> </dd> </dl> </div> ``` 成功取得 HTML 結構後,就可以繼續利用 BeautifulSoup 擷取所需的資訊。 ![網頁呈現](https://i.imgur.com/fF9CiJU.png) ![F12程式碼](https://i.imgur.com/yI7SH8O.png) ```` Ptython #正則 import re # 取得 <ul class="listInfo clearfix"></ul> 內所有元素 listInfoUl = soup.find_all("ul", class_="listInfo clearfix") num = 0 for ul in listInfoUl: # 照片 img = ul.find("img").get("data-original") # 標題 title = ul.find("a").getText() # 詳細資訊的 URL detailUrl = ul.find("a").get("href") # 價格 price = ul.find("div", class_="price").getText().strip() # 簡易說明 wordDetail = '' for de in ul.find_all("p", class_="lightBox"): wordDetail = wordDetail + " | " + de.getText().replace(" ", "").replace("\n", "") # 更新時間點 for up in ul.find_all("em"): pattern = re.compile('更新') if len(pattern.findall(up.getText())) > 0: uptime = up.getText() #印出擷取結果 print( 'title: ' + title + ", " + 'img: ' + img + "," + 'detailUrl:' + detailUrl + ", " + 'price: ' + price + ", " + 'detail:' + wordDetail + ", " + 'update' + uptime ) print("--------------") ```` 執行結果片段 ![執行結果片段](https://i.imgur.com/4Xo3uCC.png) 取得3小時內更新的內容,並製作LINE要顯示的內容。 ```` Python #表情符號 import emoji #取得3小時內更新的內容 pattern = re.compile('小時內更新') if len(pattern.findall(uptime)) > 0: pattern = re.compile('(.*)(?=小時)') hours = re.search(pattern, uptime).group(1) if int(hours) <= 3: #LINE訊息 msg = emoji.emojize('\n小幫手來啦~ :relaxed: \n租屋網更新資訊啦! :boom: \n :mega: ', use_aliases=True) + title + emoji.emojize('\n :dollar: ', use_aliases=True) + price + emoji.emojize('\n :memo: ', use_aliases=True) + wordDetail + emoji.emojize('\n :alarm_clock: ', use_aliases=True) + uptime + emoji.emojize('\n\n :tada: 看更詳細點↓網址 \n https:', use_aliases=True) + detailUrl #印出要傳送的LINE訊息 print(msg) print('-------------') ```` 執行結果片段 ![執行結果片段](https://i.imgur.com/sRa8XKu.png) 透過 LINE Notify API 送出訊息。 ```` Python #lineNotify設定 def lineNotifyMessage(token, msg, imgUrl): # hearders 這兩項必帶 # token 為 LINE Notinfy 申請的權杖 headers = { "Authorization": "Bearer " + token, "Content-Type": "application/x-www-form-urlencoded" } # message : 要顯示的文字 # imageThumbnail、imageFullsize : 要顯示的圖片 # stickerPackageId、stickerId : 貼圖 message = {'message': msg, 'imageThumbnail':imgUrl,'imageFullsize':imgUrl,'stickerPackageId':1,'stickerId':13} #透過 POST 傳送 req = requests.post("https://notify-api.line.me/api/notify", headers = headers, data = message) return req.status_code # 傳送LINE訊息 lineNotifyMessage("申請的權杖", msg, img) ```` 執行結果 ![LINE 執行結果](https://i.imgur.com/xwJfxRz.png) ## Git檔案至 GitHub 建立 Repository,輸入Repository Name,將權限設為公開(Public)。 ![建立Repository](https://i.imgur.com/GELqnfg.png) 將程式碼上傳至剛剛建立的Repository。 ``` RentHouseInfo.py #主程式 requirements.txt #告訴Heroku要安裝什麼套件 runtime.txt #告訴Heroku Python的版本 ``` ![Push至GitHub](https://i.imgur.com/Hr9z3xK.png) ## Heroku架設 [Heroku](https://www.heroku.com/)是一個平台即服務(PaaS),可自行在Heroku平台開發和佈署各種網站,它提供免費帳戶一個月一定小時的運行時間,使用量不大的話,覺得滿划算的。 建立帳號後,建立一個應用程式。 ![建立應用程式](https://i.imgur.com/yCn53kn.png) 輸入名稱。 ![輸入資料](https://i.imgur.com/iyYg1lM.png) 選擇 Deploy 頁籤,再Deployment method 選擇 GitHub,然後點選 Connect to GitHub 按鈕。 ![選擇頁簽](https://i.imgur.com/plAgpFn.png) 會跳出是否要授權Heroku與GitHub之間連動。 ![GitHub連動](https://i.imgur.com/Bwfi2ti.png) 完成連接後輸入你的Repository。 ![Repository連動](https://i.imgur.com/sZ7BL5C.png) 自動部屬。 ![自動部屬](https://i.imgur.com/FjmDCKK.png) 切換至Resources頁籤。 ![Resources](https://i.imgur.com/ynfuHWL.png) 在Add-ons區塊中搜尋Heroku Scheduler。 ![搜尋addon](https://i.imgur.com/hDmFspu.png) 新增Heroku Schedule Add-on。 ![新增Heroku Schedule](https://i.imgur.com/bkwDxGN.png) 新增完成後,點擊Heroku Scheduler,進入設定頁面。 ![Heroku Scheduler頁面](https://i.imgur.com/vxcItMP.png) 點擊 Create job 按鈕,建立一個工作。 ![建立一個工作](https://i.imgur.com/uzlXcng.png) 依照自己的需求設定。 ![設定工作](https://i.imgur.com/1o6yV79.png) <span style="color:#B5495B">Schedule只能設定每10分鐘、每小時即每天的某個時間點,且時間點為UTC時間,如果對於時間點明確需要的需自行換算時間。</span> 現在想要每三小時執行一次,所以設定每天某個時間點執行,間格為三小時。 ![設定每三小時執行](https://i.imgur.com/5DH2G7B.png) 設定完成後,等待時間到,觀察是否有正常執行。 ![測試執行1](https://i.imgur.com/rBhm7WB.png) ![測試執行2](https://i.imgur.com/m9ynTcw.png) ![測試執行3](https://i.imgur.com/P6Xg6e1.jpg) ## 參考資料 - [超簡單一鍵推播 591 租屋資訊完全免 Coding-透過 Google Sheet 與 LINE Notify](https://ithelp.ithome.com.tw/articles/10255573) - [使用LINE Notify發送訊息(Heroku+GitHub+Python)](https://rnnnnn.medium.com/%E4%BD%BF%E7%94%A8line-notify%E7%99%BC%E9%80%81%E8%A8%8A%E6%81%AF-heroku-github-python-9132ff9ebe1b) - [自建 LINE Notify 訊息通知](https://www.oxxostudio.tw/articles/201806/line-notify.html) - [LINE Notify 入門到進階應用(4) --- 傳送文字網路圖片到Line Notify 其他語言](http://white5168.blogspot.com/2017/01/line-notify-4-line-notify.html#.YD9CM9x-W01) - [Heroku - 自動執行python腳本](https://yeeinhole.github.io/2020/03/20/heroku-trelloXline/) - [Python emoji Packages](https://pypi.org/project/emoji/) - [Python emoji Charts](https://www.webfx.com/tools/emoji-cheat-sheet/)