<style> html, body, .ui-content { background-color: #333; color: #ddd; } body > .ui-infobar { display: none; } .ui-view-area > .ui-infobar { display: block; } .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { color: #ddd; } .markdown-body h1, .markdown-body h2 { border-bottom-color: #ffffff69; } .markdown-body h1 .octicon-link, .markdown-body h2 .octicon-link, .markdown-body h3 .octicon-link, .markdown-body h4 .octicon-link, .markdown-body h5 .octicon-link, .markdown-body h6 .octicon-link { color: #fff; } .markdown-body img { background-color: transparent; } .ui-toc-dropdown .nav>.active:focus>a, .ui-toc-dropdown .nav>.active:hover>a, .ui-toc-dropdown .nav>.active>a { color: white; border-left: 2px solid white; } .expand-toggle:hover, .expand-toggle:focus, .back-to-top:hover, .back-to-top:focus, .go-to-bottom:hover, .go-to-bottom:focus { color: white; } .ui-toc-dropdown { background-color: #333; } .ui-toc-label.btn { background-color: #191919; color: white; } .ui-toc-dropdown .nav>li>a:focus, .ui-toc-dropdown .nav>li>a:hover { color: white; border-left: 1px solid white; } .markdown-body blockquote { color: #bcbcbc; } .markdown-body table tr { background-color: #5f5f5f; } .markdown-body table tr:nth-child(2n) { background-color: #4f4f4f; } .markdown-body code, .markdown-body tt { color: #eee; background-color: rgba(230, 230, 230, 0.36); } a, .open-files-container li.selected a { color: #5EB7E0; } </style>} # LineBot 聊天機器人(Python+Flask+Heroku)建立紀錄 Part 2-1 : 指令爬取表特版照片(爬蟲篇) ###### tags: `LineBot` ### 使用套件 * beautifulSoup * requests 此機器人接收到特定指令後會爬取[表特版](https://www.ptt.cc/bbs/Beauty/index.html)的圖片並回傳至聊天視窗。設定為爬取前三頁所有貼文內的圖片,並隨機回傳一張照片。 ### 載入所需模組 ``` import json import os import requests import urllib.parse from bs4 import BeautifulSoup import random ``` ## 取得當前網頁所有貼文內之連結並隨機回傳 ### 使用python 登入表特版 ``` def looking_picture(url): base_url = 'https://www.ptt.cc' header = { 'User-Agent':"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0", "Cookie" : "_ga=GA1.2.1992706948.1582614518; __cfduid=d3c8d86602470d05242b056fe538d18781595137978; over18=1; __cf_bm=cc1e8fa95958d9231e1c7808f60eeebcf3a131d2-1597193458-1800-Ado72sxElw7hsP5j9giK2ykFqh8lHb109qe5PYqE/twVKIQhjxIq56FNvCHAWWT4VFF/t56l5mEbWAAY0AAHePM=; _gid=GA1.2.25046529.1597193460" } html = requests.get(url, headers = header).text soup = BeautifulSoup(html, 'lxml') # 使用BeautifulSoup 解析網頁 ``` ### 取得每篇文章的連結 進到表特版後使用Inspect Element功能檢視網頁 ![](https://i.imgur.com/VwAb365.png) 由上圖可知每篇post的連結會放在class = 'title' 的div tag 內,因此可以用以下程式碼取得部份的網站連結 ``` def looking_picture(url): ... pptdivs = soup.find_all('div',{'class':'title'}) ``` 進入所有post, 爬取所有圖片的網址,將開頭是 https://i.imgur 的連結存取到 photos 的 list 內,並使用random.choice 選擇一張照片並回傳 ``` def looking_picture(url): ... photos = [] # Enter to the link and search for each link of picture for post in pptdivs: if post.find('a'): post_link = base_url + post.find('a')['href'] post_html = requests.get(post_link, headers = header).text post_soup = BeautifulSoup(post_html, 'lxml') main_container = post_soup.find_all('div', {'id':'main-container'}) url_photos = main_container[0].find_all('a') for photo in url_photos: href_photo = photo['href'] if href_photo.startswith('https://i.imgur'): photos.append(href_photo) the_photo = random.choice(photos) return the_photo ``` ## 上一頁 只爬一張網頁感覺有點少,此function 可以讓程式去上一頁 ### 取得上一頁的網址 ![](https://i.imgur.com/v2JzMDk.png) 由Inspect 功能得到上一頁按鍵的tag位置 ``` def ptt_last_page(url): base_url = 'https://www.ptt.cc' header = { 'User-Agent':"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0", "Cookie" : "_ga=GA1.2.1992706948.1582614518; __cfduid=d3c8d86602470d05242b056fe538d18781595137978; over18=1; __cf_bm=cc1e8fa95958d9231e1c7808f60eeebcf3a131d2-1597193458-1800-Ado72sxElw7hsP5j9giK2ykFqh8lHb109qe5PYqE/twVKIQhjxIq56FNvCHAWWT4VFF/t56l5mEbWAAY0AAHePM=; _gid=GA1.2.25046529.1597193460" } ptthtml = requests.get(url, headers = header).text soup = BeautifulSoup(ptthtml, 'lxml') div_page = soup.find('div', 'btn-group-paging') last_page = div_page.find_all('a')[1]['href'] last_page_link = base_url + last_page return (last_page_link) ``` ## Main Function 執行上面兩個程式並傳回篩選出的圖片網址 ### 想爬多少頁就執行多少次,實際測試爬兩頁就花了不少時間(30 sec), 爬蟲速度需要再優化(未來課題) ``` def get_picture(): # try: url = 'https://www.ptt.cc/bbs/Beauty/index.html' gallary = [] pic1 = looking_picture(url) gallary.append(pic1) url = ptt_last_page(url) print('======================================================='+ url) pic2 = looking_picture(url) gallary.append(pic2) print(len(gallary)) the_choice_picture = random.choice(gallary) return the_choice_picture ``` ### 最後只要把回傳出來的圖片接到LineBot上就大功告成了,留給下一篇。