# 聊天機器人Chatbot 下載git跟heroku 並安裝 https://devcenter.heroku.com/articles/heroku-cli#download-and-install https://git-scm.com/downloads 登入Line Developers 設置聊天機器人 使用VS Code編輯 ```python= from flask import Flask, request, abort from linebot import(LineBotApi, WebhookHandler) from linebot.exceptions import(InvalidSignatureError) from linebot.models import * app = Flask(__name__) #Channel Access Token line_bot_api = LineBotApi('5Lya6ueGDxDPVuM9WzSZte5NzxYGXT1W35Fws7DoFMD4/o6kofCp8+o4yuGMWIuBA2njV6hY16w/y7dpDz8j3mn3C4LFsdeWaoLmwjeykDdI5YHVnp/y/whEgYZVaxg2UKsTE3CpJJMe9px2CIlnLAdB04t89/1O/w1cDnyilFU=') #Channel Secret handler = WebhookHandler('f04479c2a3743e08c4b96412d0cbcaa0') #監聽所有來自 /callback 的 Post Request @app.route("/callback",methods=['POST']) def callback(): #get X-Line_Signature header value signature = request.headers['X-Line-Signature'] #get requeset body as text body = request.get_data(as_text=True) app.logger.info("Request body: "+body) #handle webhook body try: handler.handle(body,signature) except InvalidSignatureError: abort(400) return 'OK' #處理訊息 @handler.add(MessageEvent, message=TextMessage) def handle_message(event): message = TextSendMessage(text=event.message.text) line_bot_api.reply_message(event.reply_token,message) # message = StickerSendMessage(package_id='11537',sticker_id='52002735') # # line_bot_api.reply_message(event.reply_token,message) import os if __name__=="__main__": port = int(os.environ.get('PORT',5000)) app.run(host='0.0.0.0',port=port) ``` 這是應聲鳥機器人 新增Line的webhook ![](https://i.imgur.com/xwEEXF9.png) 螢光線的地方是在heroku的專案名稱 ![](https://i.imgur.com/PMCwZyy.png) 要新增這些key跟value 開啟Terminal ![](https://i.imgur.com/YVp1x45.png) 把資料夾選到你的專案資料夾 然後登入heroku git config --global user.name "你的名字" git config --global user.email 你的信箱 git init 第一次才要輸入 之後不用 heroku git:remote -a {HEROKU_APP_NAME} 沒有大括號 git add . git commit -m "Add code" git push -f heroku master 上面的依序輸入 TemplateSendMessage ->ButtonsTemplate 按鈕介面 ->ConfirmTemplate 確認介面 ->CarouseTemplate (多個ButtonsTemplate) 訊息物件中 Image Template message提供互動式介面,會產稱一個Action,Action可以分為以下4種 1. Postback ->按下後透過action=buy&item=111傳送到後台,後台就知道user點了甚麼 2. Message ->幫使用者送出一個訊息 3. URL ->網站 4. Datetime ->告知後台user選擇的使用細節 ```python= import requests import re import random import configparser from bs4 import BeautifulSoup from flask import Flask, request, abort from imgurpython import ImgurClient from flask import Flask, request, abort from linebot import ( LineBotApi, WebhookHandler ) from linebot.exceptions import ( InvalidSignatureError ) from linebot.models import * app = Flask(__name__) #Channel Access Token line_bot_api = LineBotApi('5Lya6ueGDxDPVuM9WzSZte5NzxYGXT1W35Fws7DoFMD4/o6kofCp8+o4yuGMWIuBA2njV6hY16w/y7dpDz8j3mn3C4LFsdeWaoLmwjeykDdI5YHVnp/y/whEgYZVaxg2UKsTE3CpJJMe9px2CIlnLAdB04t89/1O/w1cDnyilFU=') #Channel Secret handler = WebhookHandler('f04479c2a3743e08c4b96412d0cbcaa0') #監聽所有來自 /callback 的 Post Request @app.route("/callback",methods=['POST']) def callback(): #get X-Line_Signature header value signature = request.headers['X-Line-Signature'] #get requeset body as text body = request.get_data(as_text=True) app.logger.info("Request body: "+body) #handle webhook body try: handler.handle(body,signature) except InvalidSignatureError: abort(400) return 'OK' def apple_news(): target_url = 'https://tw.appledaily.com/new/realtime' print('Start parsing appleNews....') rs = requests.session() res = rs.get(target_url, verify=False) soup = BeautifulSoup(res.text, 'html.parser') content = "" for index, data in enumerate(soup.select('.rtddt a'), 0): if index == 5: return content link = data['href'] content += '{}\n\n'.format(link) return content def technews(): target_url = 'https://technews.tw/' print('Start parsing movie ...') rs = requests.session() res = rs.get(target_url, verify=False) res.encoding = 'utf-8' soup = BeautifulSoup(res.text, 'html.parser') content = "" for index, data in enumerate(soup.select('article div h1.entry-title a')): if index == 12: return content title = data.text link = data['href'] content += '{}\n{}\n\n'.format(title, link) return content def oil_price(): target_url = 'https://gas.goodlife.tw/' rs = requests.session() res = rs.get(target_url, verify=False) res.encoding = 'utf-8' soup = BeautifulSoup(res.text, 'html.parser') title = soup.select('#main')[0].text.replace('\n', '').split('(')[0] gas_price = soup.select('#gas-price')[0].text.replace('\n\n\n', '').replace(' ', '') cpc = soup.select('#cpc')[0].text.replace(' ', '') content = '{}\n{}{}'.format(title, gas_price, cpc) return content def panx(): target_url = 'https://panx.asia/' print('Start parsing ptt hot....') rs = requests.session() res = rs.get(target_url, verify=False) soup = BeautifulSoup(res.text, 'html.parser') content = "" for data in soup.select('div.container div.row div.desc_wrap h2 a'): title = data.text link = data['href'] content += '{}\n{}\n\n'.format(title, link) return content def ptt_hot(): target_url = 'http://disp.cc/b/PttHot' print('Start parsing pttHot....') rs = requests.session() res = rs.get(target_url, verify=False) soup = BeautifulSoup(res.text, 'html.parser') content = "" for data in soup.select('#list div.row2 div span.listTitle'): title = data.text link = "http://disp.cc/b/" + data.find('a')['href'] if data.find('a')['href'] == "796-59l9": break content += '{}\n{}\n\n'.format(title, link) return content #處理訊息 @handler.add(MessageEvent, message=TextMessage) def handle_message(event): if event.message.text == "油價查詢": content = oil_price() line_bot_api.reply_message( event.reply_token, TextSendMessage(text=content)) return 0 if event.message.text == "PTT": content = ptt_hot() line_bot_api.reply_message( event.reply_token, TextSendMessage(text=content)) return 0 if event.message.text == "科技新報": content = technews() line_bot_api.reply_message( event.reply_token, TextSendMessage(text=content)) return 0 if event.message.text == "PanX泛科技": content = panx() line_bot_api.reply_message( event.reply_token, TextSendMessage(text=content)) return 0 if event.message.text == "開始玩": buttons_template = TemplateSendMessage( alt_text='開始玩 template', template=ButtonsTemplate( title='選擇服務', text='請選擇', thumbnail_image_url='https://i.imgur.com/fUWTqXp.jpg', actions=[ MessageTemplateAction( label='新聞', text='新聞' ), MessageTemplateAction( label='電影', text='電影' ), MessageTemplateAction( label='看廢文', text='看廢文' ) ] ) ) line_bot_api.reply_message(event.reply_token, buttons_template) return 0 if event.message.text == "新聞": buttons_template = TemplateSendMessage( alt_text='新聞 template', template=ButtonsTemplate( title='新聞類型', text='請選擇', thumbnail_image_url='https://i.imgur.com/vkqbLnz.png', actions=[ MessageTemplateAction( label='PTT', text='PTT' ), MessageTemplateAction( label='科技新報', text='科技新報' ), MessageTemplateAction( label='PanX泛科技', text='PanX泛科技' ) ] ) ) line_bot_api.reply_message(event.reply_token, buttons_template) return 0 message = TemplateSendMessage( alt_text='目錄 template', template=CarouselTemplate( columns=[ CarouselColumn( thumbnail_image_url='https://i.imgur.com/c37XTQO.png', title='選擇服務', text='請選擇', actions=[ MessageAction( label='開始玩', text='開始玩' ), URIAction( label='OP.GG', uri='https://tw.op.gg/champion/statistics' ), URIAction( label='粉絲團', uri='https://zh-tw.facebook.com/lolopgg' ) ] ), CarouselColumn( thumbnail_image_url='https://i.imgur.com/6JYzgMA.jpg', title='選擇服務', text='請選擇', actions=[ MessageAction( label='other bot', text='imgur bot' ), MessageAction( label='油價查詢', text='油價查詢' ), URIAction( label='浮動油價FB', uri='https://zh-tw.facebook.com/gas.goodlife.tw' ) ] ), CarouselColumn( thumbnail_image_url='https://i.imgur.com/p5z9Nu9.png', title='選擇服務', text='請選擇', actions=[ URIAction( label='分享 bot', uri='https://imgur.com/yW9ocfP' ), URIAction( label='TWITCH 首頁', uri='https://www.twitch.tv/' ), URIAction( label='TWITCH 頻道分類', uri='https://www.twitch.tv/directory' ) ] ) ] ) ) line_bot_api.reply_message(event.reply_token, message) import os if __name__=="__main__": port = int(os.environ.get('PORT',5000)) app.run(host='0.0.0.0',port=port) ``` pip install twder 打開terminal cd 到你的資料夾 打 python manage.py runserver 再打開一個terminal cd 到你的資料夾 打 ngrok http 8000(這是端口可以改)