2025年2月14日 星期五

Python 學習筆記 : 使用 DuckDuckGo API 搜尋網路資料 (二)

在前一篇測試中, 我們對 DuckDuckGo API 用法已有基本了解, 只要安裝第三方套件 duckduckgo-search 即可在應用程式中透過 DuckDuckGo API 搜尋文字, 圖片, 影片, 新聞等內容, 甚至可與 GPT 語言模型聊天, 參考本系列前一篇文章 :


本篇則要使用 Gradio 作為網頁應用程式介面來顯示從 DuckDuckGo 搜尋到的圖片. 


8. 使用 Gradio 製作圖片搜尋介面 : 

Gradio 是 Hugging Face 旗下的一款輕量級開放原始碼 Python web app 套件, 開發者毋須具備任何網頁前端技術 (例如 HTML, CSS, Javascript), 只需少許 Python 程式碼即可快速建構一個網頁應用程式介面, 用法參考 :


Gradio 官網提供 Playground 讓開發者線上撰寫 Web app, 網址如下 : 


在 Gradio Playgorund 上編寫的應用程式可以一鍵部署到 Hugging Face 的免費 Web app 空間 Hugging Face Space (也可付費取得更多資源), 參考 : 


Hugging Face Space 已安裝一些常用的 Python 第三方套件, 例如 Numpy, Pandas, Matplotlib 等等, 通常在 Gradio Playgorund 上可以順利執行的 Web app 發布到 Hugging Face Space 後應該均可順利運行, 如果出現找不到套件或模組的錯誤, 就要到 Hugging Face Space 上手動新增一個專案, 並在 requirement.txt 檔案中指定要安裝之第三方套件, 參考 :


不過壞消息是, 由於透過 DuckDuckGo API 搜尋資料需要 requests 或 urllib 等爬蟲套件, 但 Gradio Playground 與 Hugging Face Space 可能基於資安原因均無法執行這些爬蟲套件, 因此以下測試均在本機執行. 

Gradio 用來展示圖片的元件為 Gallery, 用法參考 : 


全部 Gradio 測試紀錄參考索引 :


測試程式碼如下 :

# gradio-duckduckgo-images-gallery-1.py
import gradio as gr
from duckduckgo_search import DDGS

def handler(query, max_results):
    results=ddgs.images(query, max_results=int(max_results))  # 需用 int() 轉成整數
    return [result['thumbnail'] for result in results]
    
ddgs=DDGS()
in1=gr.Textbox(label='輸入關鍵字', value='可愛的貓')
in2=gr.Textbox(label='設定圖片數量', value=8)
out1=gr.Gallery(label='DuckDuckGo 圖片搜尋結果', columns=4, object_fit='scale-down')
iface=gr.Interface(
    fn=handler,
    inputs=[in1, in2],
    outputs=out1,
    title='DuckDuckGo 圖片搜尋測試',
    flagging_mode='never',
    )
iface.launch()

此例設置了兩個 TextBox 輸入元件, in1 負責接收搜尋關鍵字, in2 負責接收欲取得之圖片數量 (即取前幾個搜尋結果), 這兩個參數會依序傳入處理函式 fn=handler, 分別對應到 query 與 max_results, 然後傳給 DDGS 物件的 images() 方法進行圖片搜尋, 然後從 DuckDuckGo API 回應的字典串列中, 取出 thumbnail 鍵所攜帶的縮圖 URL 組成串列傳回給 Gallery 元件顯示. 注意, 由於 Textbox 元件輸出字串, 但 max_results 參數要求為一個整數, 故需先用 int() 轉換. 

結果如下 : 




因為 Gallery 元件指定 columns=4, 所以圖片會以 4 欄呈現, 點擊這些小圖就會彈出一個較大視窗來顯示這些縮圖 (不是原始圖檔). 如果將 handler() 中的傳回值改成擷取原本圖檔的 URL 鍵 image 亦可 : 

return [result['image'] for result in results]

但因為 Gradio 的 Gallery 能顯示的圖檔尺寸有限, 太大的圖檔會無法呈現, 例如 : 




也可以用 Number 或 Slider 元件來設定圖片數量, 它們都是傳回數值, 因此毋須使用 int() 來轉換 in2 元件的傳出值, 例如 : 

# gradio-duckduckgo-images-gallery-2.py
import gradio as gr
from duckduckgo_search import DDGS

def handler(query, max_results):
    results=ddgs.images(query, max_results=max_results)
    return [result['thumbnail'] for result in results]
    
ddgs=DDGS()
in1=gr.Textbox(label='輸入關鍵字', value='可愛的貓')
in2=gr.Number(label='設定圖片數量', minimum=1, value=8, maximum=100)
out1=gr.Gallery(label='DuckDuckGo 圖片搜尋結果', columns=4, object_fit='scale-down')
iface=gr.Interface(
    fn=handler,
    inputs=[in1, in2],
    outputs=out1,
    title='DuckDuckGo 圖片搜尋測試',
    flagging_mode='never',
    )
iface.launch()

結果如下 : 





下面是使用 Slider 的範例 :

# gradio-duckduckgo-images-gallery-3.py
import gradio as gr
from duckduckgo_search import DDGS

def handler(query, max_results):
    results=ddgs.images(query, max_results=max_results)
    return [result['thumbnail'] for result in results]
    
ddgs=DDGS()
in1=gr.Textbox(label='輸入關鍵字', value='可愛的貓')
in2=gr.Slider(label='設定圖片數量', minimum=1, value=8, maximum=100, step=1)
out1=gr.Gallery(label='DuckDuckGo 圖片搜尋結果', columns=4, object_fit='scale-down')
iface=gr.Interface(
    fn=handler,
    inputs=[in1, in2],
    outputs=out1,
    title='DuckDuckGo 圖片搜尋測試',
    flagging_mode='never',
    )
iface.launch()

由於 Slider 滑動步階預設為 0.1, 因此這裡要將 step 設為 1 (上面的 Number 元件沒有 step 參數, 因為它固定為 1, 結果如下 : 



沒有留言 :