---
tags: openData
---
# 🤖 機器人下載連結
https://lin.ee/y6PTnM5

# 📅 4/8 - 4/10
> 看完了MyGO 13集動畫,想到以前看過的[派星機](https://line.me/R/ti/p/@904amzej?from=page&accountId=904amzej),決定要來做一個梗圖機器人。
# 📅 4/11 - 4/23
> 收集素材,並將截圖依台詞和表情重新命名(累)。
## 用動畫瘋Plus快速截圖
雖然網路上的MyGO梗圖和皮卡丘一樣多,但一方面畫質不一、一方面重複的圖和改圖混在一起不好整理,想來想去還不如自己去動畫瘋截。~~(順便二刷MyGO)~~
https://chromewebstore.google.com/detail/%E5%8B%95%E7%95%AB%E7%98%8B%C2%B7plus/jkpkmeimgkhodlppajjgikfcodlilmpd?hl=zh-TW


動畫瘋Plus是一個Chrome瀏覽器插件,下載以後,只要按鍵盤G就可以立刻截圖,最後按『全部下載』就可以打包成一個壓縮檔。所以我通常都是截完一集就下載一次,依集數整理成如下:

## 將圖片上傳至imgur
主要是建立一個雲端的圖庫,到時候抓圖片比較方便。
雖然傳到imgur就算是公開分享了,不過就算這是一個小型作品,但也是有3000+的圖片,有個機器人當作查找的工具,還是比較方便。
由於目標就是做出一個免費公開的小玩具,所以能不花錢,一切從簡就是這次的基本原則。

(圖片來源:[擠子(猴子)](https://store.line.me/stickershop/author/573578/zh-Hant))
:::info
如果是比較注重內容隱私,或是真的有十幾萬張圖片要整理的,也可以改用Firebase Storage等較為穩定、安全的服務。
:::
# 📅 4/24 - 5/1
> 寫機器人的程式,主要是參考以前大四寫機器人程式的方法。想要做些變化,或是深度了解原理的可以自己再去找資料研究,這邊僅列出開發過程供參考。
## 在LINE Developers建立Linebot
註冊/登入後,點選`Create new Provider` ,輸入Provider name(這還不是機器人名稱,而是擁有該機器人的帳戶名稱,基本上不會公開。)

填好以後,新帳戶就建立好了,這時選擇`Create a Messaging API Channel`

然後把一些該填的資料填一填,像是:
- **Company or owner's country or region**:所在地區選Taiwan。
- **Channel icon**:機器人的大頭貼
- **Channel name**:機器人的名稱
- **Channel description**:機器人的功能簡述
- **Category / SubCategory**:機器人的分類
其他應該都先不用動,後面也都可以再修改。
按下Create並同意LINE的條款後,應該就會出現這個畫面了(圖像僅供參考,原則上會跟你前面填的設定相關)

點進去你的Messaging API,有些設定可以先調:
- ==在上面的導覽列點選Messaging API,將Use Webhook打開==。

- ==往下滑,在LINE Official Account features調整回應設定==:

可以點選旁邊的Edit調整,比較重要的是要將Webhook打開。

- ==再往下滑,產生Channel Access Token。==

:::danger
一旦Channel Access Token流出,別人就可以透過它來控制你的機器人,所以**絕對不能讓人知道!**
:::
---
## 建立Linebot程式專案
參考 [yaoandy107大大的這篇文章](https://github.com/yaoandy107/line-bot-tutorial) 建立的,裡面主要有三個檔案:
1. **app.py**
Linebot的主程式,只要將 [這段程式](https://github.com/yaoandy107/line-bot-tutorial/blob/master/app.py) 複製到你的檔案就好。到時候要讓機器人運行的程式,會寫在`handle_message`這個function裡面。

在最上方的LineBotApi填入你的Channel Access Token,以及在WebhookHandler填入你的Channel secret。

2. **Procfile**
這個主要是後面要將機器人上傳到雲端伺服器時,給平台看的執行命令,格式為:`web: {語言}{檔案}`。
而我們是用Python開發,要託管的檔案是"app.py",所以裡面的內容就是`web: python app.py`
3. **requirements.txt**
列出所有Web Service會用到的套件,

- **line-bot-sdk**:Linebot運行Python程式時會用到的套件。
- **flask**:Python的Web框架。
- **Gunicorn**:協助部署Flask的套件。
建立好了以後,將這些檔案上傳到你的GitHub。我通常是習慣用GitHub Desktop,可以參考 [這篇文章](https://hackmd.io/@YmcMgo-NSKOqgTGAjl_5tg/HJpJk8ABU/%2F%40Albertnotes%2FB1_iKcAwI) 的做法。因為接下來要部屬到伺服器上,需要透過GitHub。
:::danger
對了,文章裡面會建議你上傳到GitHub時,權限不要設成Private,但這邊**我們反而要設成Private,因為不能被別人看到裡面的Channel Access Token。**
:::
## 部署(Deploy)到雲端伺服器 Render
將機器人部屬在雲端伺服器,是為了讓程式可以自動執行,不用一直開著電腦。
以前最常見的免費伺服器應該是Heroku,不過很可惜它在去年11月底就停用免費方案了。目前這個機器人用的伺服器是Render,雖然有一些限制,但如果你只是要跑一個機器人程式,應該是綽綽有餘。部屬方式也非常簡單。下面會說明我自己部屬的過程,也可以參考 [這篇文章](https://medium.com/starbugs/render-%E4%BE%86%E8%A9%A6%E8%A9%A6%E7%94%A8%E4%BE%86%E5%8F%96%E4%BB%A3-heroku-%E7%9A%84%E6%9C%8D%E5%8B%99%E5%90%A7-render-%E7%9A%84%E7%B6%B2%E8%B7%AF%E6%9C%8D%E5%8B%99%E9%83%A8%E7%BD%B2%E4%BB%8B%E7%B4%B9-b728e86d5716)
1. ==註冊帳號,然後點選右上角的New按鈕,選擇Web Service==

2. ==選擇Build and deploy from a Git repository==

3. ==選擇你要Connect 的 Repo==

如果左邊都沒有你要連結的Repo,可以去右邊的GitHub下方點選Configure account,設定你可以給Render存取的Repo。

4. ==填寫設定==:


- **Name**:這個Web Service的名稱。
- **Runtime**:選擇`Python 3`
- **Build Command**:(要用什麼套件建立Web Service?)輸入`pip install -r requirements.txt`
- **Start Command**:(要用什麼套件託管哪個程式?)`gunicorn app:app`
- **Instance Type**:選擇`Free`
最後按下Create New Service,在Event確認有顯示綠色的Deploy就完成了。(如果有狀況,可以點選旁邊的Logs看是發生什麼問題。)


5. ==在機器人建立 Webhook==
先複製Web Service的連結

回到LINE Developer,將它貼到Messaging API的Webhook URL,**並在最後面加上`/callback`**

:::info
2025/10/21 補充:
後面加上的 `/callback`,是我們程式的 API 路徑:

Messaging API 就是透過這個路徑執行我們的程式,所以如果 route 改成 `/webhook` 的話,Messaging API 的路由就要跟著改成 `https://xxx.onrender.com/webhook`
:::
---
## 編寫機器人程式
前置作業弄完以後,就可以開始編寫Linebot的程式碼了。
不過寫之前先整理一下我們需要哪些功能。參考派星機的功能,我們最主要的功能有三個:
:::info
1. 使用者輸入編號,機器人回傳對應的圖片。
2. 使用者輸入文字,機器人回傳圖片的名稱與編號。
3. 圖片下方會有一些按鈕,按下「抽」就會隨機回傳一張圖片
:::
除此之外,我想再新增並改良一些東西:
:::info
1. 按下「抽」時,使用者輸入的內容從"抽"改成隨機一張圖片的編號,這樣就可以知道圖片是在第幾集出現的。
2. 新增查詢歌曲功能,為每首MyGO的原創取設定一組編號,使用者輸入後就回傳歌曲的官方YouTube連結。
3. 新增一個引導使用的多頁訊息
:::
### 建立圖片索引資料庫
要實現這些功能的前提,我想應該要先建立一個查找用的資料庫,每一筆資料要包含三個元素:
:::success
- 圖片編號:機器人回傳圖片的依據,必須是唯一值,不能重複。
- 圖片名稱:組成為【圖片編號】+圖片名稱,這樣在搜尋名稱時才看得到編號。
- 圖片連結:在imgur上對應的圖片網址
:::
這個資料庫當然是要再額外寫程式自動建立(~~如果手動輸入,我大概到Ave Mujica開播都還做不完~~)。如果要讓程式自動生成,那當然就要把SOP先想好,讓程式照著SOP就能一次生成我們需要的東西,是最理想的情況。後續要維護或新增資料也比較方便。
既然要一切從簡,那也不用去搞什麼SQL了,直接用json就好。建好以後的格式應該要長這樣:
```json=
[
{
"編號": "",
"圖片名稱": "【編號】檔案名稱",
"圖片連結": "imgur網址"
},
...
...
]
```
構思好資料庫的長相後,下一步就考慮要怎麼建立裡面的內容。
### 圖片編號
圖片編號的設計,我希望可以透過英文字母去對集數做分類,也就是第一集出現的圖片,編號就用A開頭,第二集出現的圖片,編號就用B開頭,以此類推。然後每一集的截圖大概都在150張以上,但不超過400張,所以我想全部都用三位數的格式,如A001、A011、A101,這樣應該在生成與查詢上,是最整齊的。
### 圖片名稱 + 圖片網址
喔這個東西搞得我頭很痛。
一開始的構想是將圖片照集數、照名稱排序上傳到imgur,然後用selenium爬取imgur上所有網址,同時去讀取本地資料夾裡的所有檔案名稱,一次填入圖片名稱和圖片網址。
但imgur這網站很難搞,居然還有什麼「按右鍵圖片網址才會產生變化」這種奇怪的設計,所以抓了幾個網址後就很容易出現Error。
於是我改變想法,不用selenium了,也不求一次到位;先抓檔案名稱,再抓網址,然後將這兩項整理成csv檔後,再依據這份csv檔建立一份json檔。
檔案名稱用Python的os套件抓取:
```python=
import os
# 圖片所在的資料夾
directory_path = "D:\\[1]羽丘的怪女生"
# 獲取目錄中的所有文件名
files = sorted(os.listdir(directory_path))
for entry in files:
# 在這裡執行你的操作,例如讀取檔案內容等,然後將後面的副檔名拿掉
entry = entry.replace(".png","")
print(entry)
```
圖片一開始是用手動複製網址的,但這有個很大的問題:手很痛。
100張左右的圖片可能還好,但萬一增加到200張以上,按滑鼠的手指會撐不住。所以後來我找了一些方法,發現可以用 javascript 在開發者工具(F12)抓取單一頁面的圖片網址:
```javascript=
(function() {
'use strict';
// 找到所有<div class="PostContent-imageWrapper-rounded">標籤
var imageWrappers = document.querySelectorAll('div.PostContent-imageWrapper-rounded');
// 遍歷每個<div>標籤,提取<img>標籤的src屬性
imageWrappers.forEach(function(imageWrapper) {
var imageTag = imageWrapper.querySelector('img');
if (imageTag) {
var imageSrc = imageTag.getAttribute('src');
console.log(imageSrc);
}
});
})();
```

看起來只要將檔名和網址整理到csv就好了,然而在這個環節還是出了兩個問題:
:::warning
1. imgur上傳多張圖片時,有時候會亂掉。
2. Python讀取檔案的順序,和Windows檔案總管顯示的順序不一樣(猜測可能是兩者對中文開頭的排序標準不同導致的),所以Python讀取的順序,和imgur的排序是沒有對應的。
:::
所以,需要想個辦法將imgur的圖片順序,整理成和Python讀取的順序相同。
一開始想到的改善方法是:用imgur的Rearrange功能,將圖片手動拖曳重新排序後,把網址一次複製下來。但是老問題,按滑鼠的手很痛。
所以後來決定用google sheet輔助:將檔案名和網址分成兩列,然後替每組檔案名編號,再去找每個圖片網址對應的檔名編號,最後再用資料→排序的功能將網址和編號一起排序,最後匯出成csv檔。

### 建立json檔
為求保險,這邊我是以一集為單位建立pic_1、pic_2......,再合併成一個完整的pic_database.json。
首先測試建立pic_1.json:
```python=
import csv
import json
# 指定 CSV 和 JSON 檔案路徑
FIRST_LETTER = "A"
csv_file_path = "圖片名稱/圖片網址csv檔的路徑"
json_file_path = "json建立後要存放的位置"
def create_json_file(csv_file, json_file):
data = []
with open(csv_file, mode='r', newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
for i, row in enumerate(reader, start=1):
# 格式化編號為 A001、A002 等形式
number = FIRST_LETTER + str(i).zfill(3)
data.append({
"編號": number,
"圖片名稱": "【" + number + "】" + row["圖片名稱"],
"圖片連結": row["圖片連結"]
})
# 將資料寫入 JSON 檔案
with open(json_file, 'w', encoding='utf-8') as jsonfile:
json.dump(data, jsonfile, ensure_ascii=False, indent=4)
# 呼叫函式創建 JSON 檔案
create_json_file(csv_file_path, json_file_path)
print("JSON文件已生成。")
```
如果順利生成的話,那就可以把2~13集的csv檔逐一建立,然後逐一轉換成json檔,最後就可以合併成完整的圖片資料庫了。
- pic_database.json
```json=
[
{
"編號": "A001",
"圖片名稱": "【A001】12月12日發現塵埃",
"圖片連結": "https://imgur.com/OJ990M9.png"
},
{
"編號": "A002",
"圖片名稱": "【A002】OK繃",
"圖片連結": "https://imgur.com/FiZcVco.png"
},
...
...
{
"編號": "M281",
"圖片名稱": "【M281】驚訝(燈)",
"圖片連結": "https://i.imgur.com/DJGsWww.png"
},
{
"編號": "M282",
"圖片名稱": "【M282】點頭(燈)",
"圖片連結": "https://i.imgur.com/CilECbi.png"
}
]
```
:::danger
**💥 關於pic_database的位置(重要!)**
請將它和app.py放在相同位置,不要放在其他資料夾裡,並使用相對路徑。不然伺服器似乎不會管app.py所在資料夾以外的其他檔案。
:::
### 機器人的回應方式
建完資料庫後,就可以開始設計回傳圖片的邏輯控制了。
基本上我們需要用到的回應方式,就只有文字和圖片訊息而已,而在Linebot要設定這兩種訊息的函數如下:
- 文字訊息:
```python=
line_bot_api.reply_message(event.reply_token, TextSendMessage(text="機器人要回傳的文字"))
```
- 圖片訊息:
```python=
line_bot_api.reply_message(event.reply_token, ImageSendMessage(
original_content_url = "機器人發送的圖片路徑/連結",
preview_image_url = "LINE聊天室顯示的圖片路徑/連結"
))
```
~~也就是說,如果有人存心整你,它可以讓你預先看到的圖片,和實際點開的圖片長得不一樣,或許可以藉機偷渡一些奇怪的東西......~~
接下來,就先把前面列出的三點功能先做出來。
#### ==1. 使用者輸入編號,機器人回傳對應的圖片。==
首先我的構想是,先確認輸入的內容是不是圖片編號,也就是1個英文字母+3個數字的格式,這邊可以用正規表達式(Regular expression)進行檢查。
- 如果符合,就去pic_database以編號為索引尋找對應的圖片網址,回傳image message
- 如果符合但不存在,就回傳錯誤訊息(error message)
整理好了以後,就可以開始實作了。這邊為了看起來比較整齊,將正規表達式的檢查拆成`validate_image_message()`,尋找圖片網址拆成`search_images()`兩個函式:
```python=
# 檢查編號格式 (IMG)
error_message = "找不到圖片"
json_img_filepath = "pic_database.json的路徑"
def validate_image_message(message):
pattern = "^[A-Za-z]\\d{3}$"
return re.match(pattern, message)
# 讀取json查找圖片連結
def search_images(message):
with open(json_img_filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
for entry in data:
if message == entry['編號']:
return entry['圖片連結']
# 如果沒有找到完全匹配的編號,則回傳error message
return error_message
# 程式執行區塊
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
message = event.message.text
# 搜尋使用者輸入的訊息是否與pic_database的"編號"完全符合
if validate_image_message(message):
img_link = search_images(message)
# 如果沒有找到完全匹配的編號,則回傳error message
if img_link == error_message:
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=error_message))
else:
line_bot_api.reply_message(event.reply_token, ImageSendMessage(
original_content_url = img_link,
preview_image_url = img_link
)
)
```
:::info
❓ **自己寫的function要放在哪裡?**
需放在`@app.route("/callback", methods=['POST'])`這一行的上面,因為下面是LINE處理訊息與執行程式的區塊。
:::
#### ==2. 使用者輸入文字,機器人回傳圖片的名稱與編號。==
這邊的構想是打算設計模糊搜尋的功能,輸入一段文字後,就去pic_database把所有包含這段文字的圖片標題,全部抓出來暫存在一個list,然後分段並發送文字訊息。
要用模糊搜尋,就代表除了我們設定的特定關鍵字以外,其餘的輸入都要套用這個方式去做回應,所以這段程式必須要放在執行區塊的最後面;**先確認輸入的內容是否為特定關鍵字,不是的話再套用模糊搜尋。**
一樣,為了版面整齊,於是將尋找圖片標題的功能獨立成函式`search_names()`:
```python=
# 搜尋圖片名稱與對應編號
def search_names(keyword):
result = []
with open(json_img_filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
for item in data:
if keyword in item['圖片名稱']:
result.append(item['圖片名稱'])
return result
# 程式執行區塊
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
message = event.message.text
# 模糊查詢
search_result = search_names(message)
if search_result:
reply_message = "\n".join(search_result)
else:
reply_message = "找不到標題。"
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=reply_message))
```
#### ==3. 圖片下方會有一些按鈕,按下「抽」就會隨機回傳一張圖片==
在派星機裡面,有一個功能是機器人回傳圖片後,圖片下面會出現一些小按鈕,一開始我還不知道那是什麼,查過了以後才知道那是Linebot裡面一個叫Quick Reply的功能,可以把它想成快捷鍵,讓使用者只要按下按鈕,就可以輸入預設的訊息。
只要先建立好Quick Reply的物件,再將它添加到image_message裡面就可以了,除此之外,我還想增添一個「選單」的按鈕,讓它按下之後會輸入"menu":
```python=
# 程式執行區塊
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
message = event.message.text
# 創建 QuickReplyButton 物件,設定按鈕的標籤和觸發動作(抽)
random_button = QuickReplyButton(
action=MessageAction(label="抽", text=random_code())
)
# 創建 QuickReplyButton 物件,設定按鈕的標籤和觸發動作(選單)
menu_button = QuickReplyButton(
action=MessageAction(label="選單", text="menu")
)
# 創建 QuickReply 物件,將按鈕添加到 QuickReply 中
quick_reply = QuickReply(items=[random_button, menu_button])
```
```python=
# 添加到image message裡面
line_bot_api.reply_message(event.reply_token, ImageSendMessage(
original_content_url = img_link,
preview_image_url = img_link,
quick_reply=quick_reply
))
```
裡面的`random_code()`函式,就是我要設計的隨機抽號功能。
我希望它可以抽出一組圖片編號(1個英文字母+3個數字),但要留意的是,每一集的圖片總數並不一樣,比如說MyGO第一集截了166張,第二集截了185張,假如你隨機產生的範圍只到166,那B167 ~ B185就永遠不會出現;反之,如果隨機產生的範圍到185,那A167 ~ A185就是無意義的回傳,因為不存在。
所以我的做法是:幫每一集代表的英文字母,依照截下的圖片總數設定數字上限,雖然單純,但還是有用的吧。
```python=
# 隨機抽號
def random_code():
# 定義字典
code = {
'A': 166,
'B': 185,
'C': 158,
'D': 273,
'E': 283,
'F': 193,
'G': 129,
'H': 332,
'I': 248,
'J': 288,
'K': 390,
'L': 236,
'M': 282
}
# 從字典中隨機選擇一個鍵
random_letter = random.choice(list(code.keys()))
# 根據鍵找到對應的值
max_value = code[random_letter]
# 隨機生成一個1到max_value的數字
random_number = random.randint(1, max_value)
# 將隨機生成的數字補零至3位數字
random_number_str = str(random_number).zfill(3)
# 將字母和數字組合成一個字串並回傳
return random_letter + random_number_str
```
### 後續增加的功能
到這邊,參考派星機的三項功能就都建立完成了。
接下來這些是我自己想添加的新功能:
#### ==1. 新增查詢歌曲功能==
MyGO作為一部樂隊少女動畫,它的音樂絕對是值得推薦的(~~尤其很多人一定是透過梗圖才認識這部動畫~~),除了玩梗,也希望可以讓其他人聽一聽MyGO的歌。

好的,回到正題。
我希望機器人可以回傳MyGO官方YouTube的MV連結。MyGO的原創歌曲目前共有18首,考量到這數量沒有很多,所以也不需要再做額外的查詢功能,用"list"作為關鍵字,一次列出所有歌曲的編號與名稱就好。
為了往後方便整理,我想將音樂資訊跟圖片資訊區別開來;音樂編號的格式以MUSIC開頭,後面加上三位數字;另外再新建一個音樂資料庫
music_database.json,只有18首歌,那就手動建立就好。
- music_database.json
```json=
[
{
"編號": "MUSIC001",
"影片名稱": "【MUSIC001】春日影",
"影片連結": "https://youtu.be/-kZBuzsZ7Ho?si=3JdzOLWXqAsn27gd"
},
{
"編號": "MUSIC002",
"影片名稱": "【MUSIC002】碧天伴走",
"影片連結": "https://youtu.be/zsO9_fZP2Uc?si=tll4CFVbhqEcYxzg"
},
...
...
{
"編號": "MUSIC018",
"影片名稱": "【MUSIC018】輪符雨",
"影片連結": "https://youtu.be/xNF9semW-Ng?si=uFRtyh0oSVQ6_CYP"
}
]
```
```python=
json_music_filepath = 'music_database.json'
# 檢查編號格式 (MUSIC)
def validate_music_message(message):
pattern = "MUSIC\\d{3}$"
return re.match(pattern, message)
# 讀取json查找音樂連結
def search_musics(message):
with open(json_music_filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
for entry in data:
if message == entry['編號']:
return entry['影片連結']
# 如果沒有找到完全匹配的編號,則回傳預設訊息
return error_message
# 列出影片編號清單
def live_list(keyword):
result = []
with open(json_music_filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
for item in data:
result.append(item['影片名稱'])
return result
# 程式執行區塊
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
message = event.message.text
# 顯示歌曲編號與名稱清單
if("list" in message):
lives = "\n".join(live_list(message))
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=lives))
# 搜尋使用者輸入的訊息是否與music_database的"編號"完全符合
if(validate_music_message(message)):
music_link = search_musics(message)
# 如果沒有找到完全匹配的編號,則回傳預設訊息
if(music_link == error_message):
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=error_message))
else:
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=music_link))
```
#### ==2. 新增一個引導使用的多頁訊息==
這功能倒是不需要寫程式。
在 Line official account manager,找到你機器人的主頁,在左邊工具列「訊息項目」裡面,點選「多頁訊息」就可以開始建立一個新的多頁訊息了。

你可以設定要幾個頁面、圖片、文字說明、輸入的訊息類型等。建立完以後,再去「自動回應訊息」設定呼叫多頁訊息的關鍵字。

# 📅 5/2 - 5/13
> 整理剩下的json索引,發布下載連結到巴哈姆特小屋。
其實程式寫好的時候,我的圖片只整理到第7集而已 :D
不過流程都已經規劃好了,所以基本上就是流水線作業,考驗耐心而已。
- 5/14,在[巴哈姆特小屋](https://home.gamer.com.tw/homeindex.php?owner=steven051225)發布機器人的使用介紹與說明。
- 5/15,將機器人命名為"ANON TOKYO"
- 5/24,更新在[個人網站](https://sites.google.com/view/littleducklittlecreate/)。

# 📅 5/18
## 如果輸入關鍵字就能找到圖片,那不是很好嗎?
這是將機器人PO到巴哈小屋以後,有位巴友留言詢問的功能。
最初我只是想嘗試做出派星機擁有的功能,所以沒想到這一點。
被他這樣一問,我認真思考了一下,赫然發現其實如果是用json儲存資料的話,**可以用標題當作查找圖片網址的索引啊!**
诶,辦得到耶。
雖然有些圖片的名稱是重複的,可能無法準確回傳使用者想要的圖片,但如果是**搜尋資料只有一筆的情況**,應該就可以讓機器人不回傳文字索引,直接回傳那唯一符合條件的圖片,這樣還可以讓操作減少一個步驟,可行!
於是我著手修改了一下查找圖片的函式:
```python=
# 搜尋圖片名稱與對應編號
def search_names(keyword):
result = []
with open(json_img_filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
for item in data:
if keyword in item['圖片名稱']:
result.append(item['圖片名稱'])
# 當只有一組搜尋結果時,就不需回傳文字,直接回傳圖片網址
if len(result) == 1:
URLindex = result.pop()
with open(json_img_filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
for item in data:
if URLindex in item['圖片名稱']:
result.append(item['圖片連結'])
return result
# 程式執行區塊
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
message = event.message.text
# 模糊查詢
# 如果只有一組查詢結果,就回傳圖片,多於一組則回傳文字清單
search_result = search_names(message)
if len(search_result) == 1:
line_bot_api.reply_message(event.reply_token, ImageSendMessage(
original_content_url = search_result[0],
preview_image_url = search_result[0],
quick_reply=quick_reply
))
else:
if search_result:
reply_message = "\n".join(search_result)
else:
reply_message = "我沒說過那種話。"
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=reply_message))
```
這樣就可以用關鍵字尋找圖片連結了。
這個修改真的超級有感,查詢瞬間變得方便許多。

# 📅 10/4
## 將機器人加入群組
很簡單但我一直沒注意到的功能。(笑)
你可以將『ANON TOKYO』加入到 Line 的群組裡面,只要有使用者輸入對應的關鍵字,機器人一樣會回覆訊息到群組裡。

要開啟這個功能,只要去 Line Developer 打開 ==Allow bot to join group chats== 就可以了。


# 🎸 總結
機器人上線後一個禮拜,就有超過300人加入好友,相當感謝各位喜歡ANON TOKYO,果然是最佳選擇(?。🙏
寫這篇文章我盡可能用口語化的方式把過程完整呈現出來,因為我很清楚程式開發的過程中,構思、嘗試、除錯是相當重要的必經之路。我希望能夠將這些經驗分享出來,給自己,也給他人當作未來嘗試或改良的參考。
另外,關於文章提到的程式部分,絕大多數都是讓ChatGPT幫我生成的。就我這次使用的經驗來看,只要你能逐一拆解需求,表達出你想完成的步驟,並且提供一個輸出範例給它,ChatGPT真的可以省去很多找資料和打字的時間。
比如說,找圖片連結的函式其實是這樣來的:
:::success
可以幫我寫一支Python程式嗎?要在Linebot的handle_message()區塊執行的:
我希望它可以讀取一份外部的Json文件,索引有"編號"、"圖片名稱"、"圖片連結"共三個。
然後去辨識使用者輸入的訊息,將它與Json文件中的"編號"進行比對,如果有完全符合的索引,讓機器人回傳對應的圖片連結。
比如說,如果使用者輸入"A073",那就去Json文件尋找是否有"編號"完全符合"A073",如果有,機器人就回傳"A073"的"圖片連結;如果沒有,那機器人就回傳"有點不太能想像呢。"
:::
```python=
import json
def handle_message(user_input):
# 讀取外部的Json文件
with open('your_json_file.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# 搜尋使用者輸入的訊息是否與"編號"完全符合
for entry in data:
if user_input == entry['編號']:
return entry['圖片連結']
# 如果沒有找到完全匹配的編號,則回傳預設訊息
return "有點不太能想像呢。"
# 在這裡呼叫 handle_message 函式並將使用者輸入的訊息傳遞給它
user_input = input("請輸入訊息:")
response = handle_message(user_input)
print(response)
```
儘管不完全符合我們的需求,但只要簡單修改一下,就可以套用到你的機器人裡面了。
雖然說看起來很方便,但條件如果給的不夠具體,有時候ChatGPT還是會生出一些慘不忍睹的東西出來;想要準確地下達指令,拆解重組這些程式,還是要對程式的運作流程有一定程度的了解跟想像。所以我個人會覺得,ChatGPT不會取代軟體工程師,但會放大體現出工程師在程式觀念與熟悉程度的差異;邏輯越清晰的工程師,將會越接近心想事成的境界。
動作慢的可能會變快,但動作快的一定會更快,快還要更快。

(圖片來源:[擠子(猴子)](https://store.line.me/stickershop/author/573578/zh-Hant))
對不起,開玩笑的。最後再讓我講幾句話。
只要你不是慣老闆,清楚知道自己想做的事,ChatGPT就能幫你省下很多時間。
最後,MyGO真的是一部很棒的作品。
雖然對有些大佬來說可能只是很簡單的作品,但我很高興自己有堅持到最後,做出"ANON TOKYO"這個機器人。
即使迷茫,我也想要繼續前進。
希望未來,有越來越多人加入MyGO工讀生的行列。
希望未來,有人能做出JOJO或刃牙的梗圖機器人,甚至是更猛的酷東西。



# 📅 2025/10/21

從第一次就業,到第一次離職;
從 Win10 釘子戶,到 Win11 萌新,
經過不知第幾次的針眼與拖延症發作,
阿農或許會遲到,
但一輩子的事,沒有遲到這回事。