2025年3月22日 星期六

Python 學習筆記 : 使用 SerpAPI 取得 Google 搜尋結果

今天因為測試 OpenAI API 需要用到 Google 搜尋來詢問與時事相關問題時, 發現之前使用的 googlesearch-python 套件沒有傳回任何結果 : 

>>> from googlesearch import search   
>>> keywords='2024台灣總統大選是誰當選?'   
>>> items=search(keywords, advanced=True, num_results=3)      
>>> for item in items:  
  print(f'標題:{item.title}')
  print(f'標題:{item.description}')
  print(f'標題:{item.url}\n')
  
執行結果是空白, 詢問 ChatGPT 答覆是此套件可能已經無法使用, 建議使用 SerpAPI 來取得谷歌搜尋結果, 但必須先註冊帳號取得 API Key 才能使用. 


1. 註冊 SerpAPI 帳號 : 

到 SerpAPI 官網按右上角的 "Register" 註冊帳號, 免費帳戶每個月可搜尋 100 次 (平均一天只能使用 33 次, 好像有點小氣) :





可以用 Google 或 GitHub 帳號快速註冊, 但我習慣用 Hinet 郵件註冊, 填好姓名, Email 與設定密碼後按底下的 Sign Up 鈕, 它會寄一封驗證信到信箱, 去信箱收信並按下信中的確認超連結 : 




這時會開啟電話驗證頁面, 在底下 Verification code 欄位中先點前面的國籍選擇台灣, 然後輸入自己的手機號碼, 按 Send Code 鈕 : 




然後收取手機簡訊, 將 6 碼驗證碼貼到 Verification code 欄後按 Verify 鈕 :




按底下的 Subscribe 鈕即完成註冊並顯示 Dashboard 頁面 :





往下拉到 Your private API Key 就可以看到使用 API 所需的金鑰, 按右邊的按鈕複製到文字檔中保存備用 : 




有了 API Key 接下來要安裝 API 的套件. 


2. 安裝 google-search-results 套件 :   

用 pip 安裝 google-search-results 套件 : 

D:\python\test>pip install google-search-results   
Collecting google-search-results
  Downloading google_search_results-2.4.2.tar.gz (18 kB)
  Preparing metadata (setup.py) ... done
Requirement already satisfied: requests in c:\users\tony1\appdata\roaming\python\python310\site-packages (from google-search-results) (2.31.0)
Requirement already satisfied: charset-normalizer<4,>=2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from requests->google-search-results) (3.2.0)
Requirement already satisfied: idna<4,>=2.5 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from requests->google-search-results) (3.4)
Requirement already satisfied: urllib3<3,>=1.21.1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from requests->google-search-results) (1.26.19)
Requirement already satisfied: certifi>=2017.4.17 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from requests->google-search-results) (2023.7.22)
Building wheels for collected packages: google-search-results
  Building wheel for google-search-results (setup.py) ... done
  Created wheel for google-search-results: filename=google_search_results-2.4.2-py3-none-any.whl size=32077 sha256=6675aa38f27d33c50a5ce0f9af5d634abe719b015fe63b2326a5a926094321fe
  Stored in directory: c:\users\tony1\appdata\local\pip\cache\wheels\d3\b2\c3\03302d12bb44a2cdff3c9371f31b72c0c4e84b8d2285eeac53
Successfully built google-search-results
Installing collected packages: google-search-results
Successfully installed google-search-results-2.4.2

雖然安裝的套件名稱是, 但匯入使用時卻要用 serpapi 這個套件名稱 : 

>>> import serpapi  

用 dir() 檢視套件內容 : 

>>> dir(serpapi)   
['AppleAppStoreSearch', 'BaiduSearch', 'BingSearch', 'DuckDuckGoSearch', 'EbaySearch', 'GoogleScholarSearch', 'GoogleSearch', 'HomeDepotSearch', 'NaverSearch', 'SerpApiClient', 'WalmartSearch', 'YahooSearch', 'YandexSearch', 'YoutubeSearch', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'apple_app_store_search', 'baidu_search', 'bing_search', 'constant', 'duck_duck_go_search', 'ebay_search', 'google_scholar_search', 'google_search', 'home_depot_search', 'naver_search', 'pagination', 'serp_api_client', 'serp_api_client_exception', 'walmart_search', 'yahoo_search', 'yandex_search', 'youtube_search'] 

可見此 API 套件支援非常多搜尋引擎, 除了 Google 外還可以搜尋 DuckDuckGo, Bin, Yahoo 等, 但本篇只會用到其中的 GoogleSearch 類別 :

>>> type(serpapi.GoogleSearch)   
<class 'type'>


3. 用 GoogleSearch 物件搜尋 :   

首先從 serpapi 匯入 GoogleSearch 類別 : 

>>> from serpapi import GoogleSearch    

然後呼叫其建構式 GoogleSearch() 並傳入一個參數字典 params 來建立一個 GoogleSearch 物件 : 

GoogleSearch(params)  

此 params 參數字典的常用鍵值如下表所示 : 


參數名稱 說明
q 搜尋關鍵字, 例如 "2024台灣總統大選"
num 設定結果數量 (最多 100), 例如 num=10 取得 10 筆結果
start 設定從第幾筆開始 (用於分頁), 例如 start=10 從第 11 筆開始
gl 設定國家代碼, 例如 "tw" (台灣), "us" (美國)
hl 設定語言,例如 "zh-TW" (繁體中文), "en" (英文)
safe 是否啟用安全搜尋, 例如 "active" (開啟), "off" (關閉)
api_key SerpAPI 提供的 API Key, 例如 "你的 API Key"


例如搜尋 2024 台灣總統當選人 : 

>>> params={
    'q': '2024台灣總統大選是誰當選?',
    'api_key': '我的 API Key', 
    'num': 3,
    'gl': 'tw',
    'hl': zh-tw'
    }

將其傳入 GoogleSearch() 建立一個 GoogleSearch 物件 : 

>>> search=GoogleSearch(params)   
>>> type(search)   
<class 'serpapi.google_search.GoogleSearch'> 

用 dir() 檢視 GoogleSearch 物件成員 :

>>> dir(search)   
['BACKEND', 'SERP_API_KEY', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'construct_url', 'engine', 'get_account', 'get_dict', 'get_dictionary', 'get_html', 'get_json', 'get_location', 'get_object', 'get_raw_json', 'get_response', 'get_results', 'get_search_archive', 'make_pyobj', 'pagination', 'params_dict', 'timeout']

可以呼叫所提供的 get_xxx() 方法取得搜尋結果, 例如呼叫 get_dict() 會取得字典型態之結果 : 

>>> results=search.get_dict()   
>>> type(results)   
<class 'dict'>

用 keys() 方法檢視此字典之鍵 :

>>> results.keys()   
dict_keys(['search_metadata', 'search_parameters', 'search_information', 'organic_results', 'related_searches', 'pagination', 'serpapi_pagination'])

搜尋結果主要是放在 organic_results 這個鍵裡面, 此鍵主要儲存 Google 搜尋主要的自然搜尋結果 (即非廣告的結果) : 

>>> results['organic_results']     
[{'position': 1, 'title': '第16任總統副總統選舉', 'link': 'https://db.cec.gov.tw/ElecTable/Election/ElecTickets?dataType=tickets&typeId=ELC&subjectId=P0&legisId=00&themeId=4d83db17c1707e3defae5dc4d4e9c800&dataLevel=C&prvCode=00&cityCode=000&areaCode=00&deptCode=000&liCode=0000', 'redirect_link': 'https://www.google.com/url?sa=t&source=web&rct=j&opi=89978449&url=https://db.cec.gov.tw/ElecTable/Election/ElecTickets%3FdataType%3Dtickets%26typeId%3DELC%26subjectId%3DP0%26legisId%3D00%26themeId%3D4d83db17c1707e3defae5dc4d4e9c800%26dataLevel%3DC%26prvCode%3D00%26cityCode%3D000%26areaCode%3D00%26deptCode%3D000%26liCode%3D0000&ved=2ahUKEwjBq-zWyKGMAxXtSzABHd6WD6oQFnoECB4QAQ', 'displayed_link': 'https://db.cec.gov.tw › ElecTable › Election › ElecTickets', 'favicon': 'https://serpapi.com/searches/67e0b597a87cda1dbcb7f08f/images/f9b7843ebcee3773ad58dd96752619e182d6d5ca2488e6e49be838c999102248.png', 'snippet': '第16任總統副總統選舉 ; 金門縣. 柯文哲. /吳欣盈. 賴清德. /蕭美琴. 侯友宜. /趙少康. 1. 2. 3. 13,038. 4,569. 28,005. 28.58%. 10.02%. 61.40% ; 基隆市. 柯文哲. /吳欣盈.', 'snippet_highlighted_words': ['總統選舉'], 'source': '選舉資料庫'}, {'position': 2, 'title': '2024年中華民國總統選舉', 'link': 'https://zh.wikipedia.org/zh-tw/2024%E5%B9%B4%E4%B8%AD%E8%8F%AF%E6%B0%91%E5%9C%8B%E7%B8%BD%E7%B5%B1%E9%81%B8%E8%88%89', 'redirect_link': 'https://www.google.com/url?sa=t&source=web&rct=j&opi=89978449&url=https://zh.wikipedia.org/zh-tw/2024%25E5%25B9%25B4%25E4%25B8%25AD%25E8%258F%25AF%25E6%25B0%2591%25E5%259C%258B%25E7%25B8%25BD%25E7%25B5%25B1%25E9%2581%25B8%25E8%2588%2589&ved=2ahUKEwjBq-zWyKGMAxXtSzABHd6WD6oQFnoECCAQAQ', 'displayed_link': 'https://zh.wikipedia.org › zh-tw › 2024年中華民國總統...', 'favicon': 'https://serpapi.com/searches/67e0b597a87cda1dbcb7f08f/images/f9b7843ebcee3773ad58dd96752619e16639a9f527bc1f87bab180ae788ac04d.png', 'snippet': '本次是繼2000年後再度未有任一候選人得票率過半的總統選舉,亦是自總統直選以來,首度由同一政黨連續三次獲勝。蔡英文八年執政雖成功交棒,但維持執政地位的民進黨則在同日 ...', 'snippet_highlighted_words': ['總統選舉'], 'source': '维基百科'}, {'position': 3, 'title': '2024 總統大選即時開票', 'link': 'https://event.gvm.com.tw/2024presidential_election/votingresults_president.html', 'redirect_link': 'https://www.google.com/url?sa=t&source=web&rct=j&opi=89978449&url=https://event.gvm.com.tw/2024presidential_election/votingresults_president.html&ved=2ahUKEwjBq-zWyKGMAxXtSzABHd6WD6oQFnoECCIQAQ', 'displayed_link': 'https://event.gvm.com.tw › votingresults_president', 'favicon': 'https://serpapi.com/searches/67e0b597a87cda1dbcb7f08f/images/f9b7843ebcee3773ad58dd96752619e162d8bff986619777e960b531be99ef7f.png', 'snippet': '2024總統大選在即,在賴清德、侯友宜、柯文哲競逐的局勢下,最終誰會拿下總統大位?台灣會迎來新一次的政黨輪替嗎?《遠見》統合各候選人政見,針對選戰熱門關鍵字、候選人 ...', 'snippet_highlighted_words': ['2024總統大選', '台灣'], 'source': '遠見雜誌'}]

可見 organic_results 鍵的值是一個字典串列, 其元素為每一筆搜尋結果, 此處因為指定 num=3, 所以總共有三筆 : 

>>> type(results['organic_results'])  
<class 'list'>
>>> len(results['organic_results'])      
3

串列中的每個字典的鍵與說明如下表所示 :


搜尋結果字典的鍵名 說明
position 該結果在 Google 搜尋結果中的排名 (位置編號)
title 搜尋結果的標題, 通常與網頁標題相符
link 該搜尋結果的網址 (URL)
redirect_link 如果有 Google 重定向, 這裡會包含重定向後的 URL
displayed_link 在 Google 搜尋結果中顯示的網址 (可能與原始 `link` 不完全相同, 例如省略 `https://` 或 `www.`)
favicon 該網站的圖示 (favicon) 圖片 URL
snippet 該搜尋結果的簡短摘要, 通常來自該網頁的 `meta description` 或 Google 提取的內容
snippet_highlighted_words 在 `snippet` 中被 Google 強調的關鍵字列表 (可能是搜尋字詞的變體或相關詞)
source 如果結果來自特定的新聞來源或平台, 這裡會顯示來源名稱


也可以呼叫 results 字典的 get() 方法並傳入 'organic_results', 並指定一個空串列作為預設的回傳值, 迭代回傳之字典串列並透過上表中的鍵名即可取得標題, 摘要, 與網址等 : 

>>> for result in results.get('organic_results', []):   
    print(f'標題: {result["title"]}')
    print(f'描述: {result["snippet"]}')
    print(f'網址: {result["link"]}\n')   
  
標題: 第16任總統副總統選舉
描述: 第16任總統副總統選舉 ; 金門縣. 柯文哲. /吳欣盈. 賴清德. /蕭美琴. 侯友宜. /趙少康. 1. 2. 3. 13,038. 4,569. 28,005. 28.58%. 10.02%. 61.40% ; 基隆市. 柯文哲. /吳欣盈.
網址: https://db.cec.gov.tw/ElecTable/Election/ElecTickets?dataType=tickets&typeId=ELC&subjectId=P0&legisId=00&themeId=4d83db17c1707e3defae5dc4d4e9c800&dataLevel=C&prvCode=00&cityCode=000&areaCode=00&deptCode=000&liCode=0000

標題: 2024年中華民國總統選舉
描述: 本次是繼2000年後再度未有任一候選人得票率過半的總統選舉,亦是自總統直選以來,首度由同一政黨連續三次獲勝。蔡英文八年執政雖成功交棒,但維持執政地位的民進黨則在同日 ...
網址: https://zh.wikipedia.org/zh-tw/2024%E5%B9%B4%E4%B8%AD%E8%8F%AF%E6%B0%91%E5%9C%8B%E7%B8%BD%E7%B5%B1%E9%81%B8%E8%88%89

標題: 2024 總統大選即時開票
描述: 2024總統大選在即,在賴清德、侯友宜、柯文哲競逐的局勢下,最終誰會拿下總統大位?台灣會迎來新一次的政黨輪替嗎?《遠見》統合各候選人政見,針對選戰熱門關鍵字、候選人 ...
網址: https://event.gvm.com.tw/2024presidential_election/votingresults_president.html

由於通常都是搜尋繁體中文資料, 因此我寫了如下的 search_google() 來簡化 API 的調用 : 

>>> def search_google(query, serpapi_key, num=3, gl='tw', hl='zh-tw'):
    params={
        'q': query,
        'api_key': serpapi_key,
        'num': num,
        'gl': gl,
        'hl': hl
        }
    search=GoogleSearch(params)
    results=search.get_dict()
    return results.get('organic_results', [])

此函式已預設指定傳回最前面 3 筆繁體中文結果, 呼叫時只要傳入要搜尋的關鍵字 query 與 API Key 即可, 若有搜尋到資料會傳回一個包含 title (標題), snippet (描述), 與 url (網址) 等鍵的字典串列, 若沒有搜尋結果就傳回空字串, 例如 :

>>> results=search_google(query, serpapi_key)   
>>> type(results)  
<class 'list'>  
>>> len(results)  
3
>>> type(results[0])   
<class 'dict'>

可見傳回了包含 3 筆搜尋結果字典的串列, 用迴圈迭代此串列元素並顯示 title, snippet, 與 url 這三個鍵之值 : 

>>> for result in results:   
    print(f'標題: {result["title"]}')
    print(f'描述: {result["snippet"]}')
    print(f'網址: {result["link"]}\n')  
  
標題: 2024年中華民國總統選舉
描述: 本次是繼2000年後再度未有任一候選人得票率過半的總統選舉,亦是自總統直選以來,首度由同一政黨連續三次獲勝。蔡英文八年執政雖成功交棒,但維持執政地位的民進黨則在同日 ...
網址: https://zh.wikipedia.org/zh-tw/2024%E5%B9%B4%E4%B8%AD%E8%8F%AF%E6%B0%91%E5%9C%8B%E7%B8%BD%E7%B5%B1%E9%81%B8%E8%88%89

標題: 第16任總統副總統選舉
描述: 第16任總統副總統選舉 ; 金門縣. 柯文哲. /吳欣盈. 賴清德. /蕭美琴. 侯友宜. /趙少康. 1. 2. 3. 13,038. 4,569. 28,005. 28.58%. 10.02%. 61.40% ; 基隆市. 柯文哲. /吳欣盈.
網址: https://db.cec.gov.tw/ElecTable/Election/ElecTickets?dataType=tickets&typeId=ELC&subjectId=P0&legisId=00&themeId=4d83db17c1707e3defae5dc4d4e9c800&dataLevel=C&prvCode=00&cityCode=000&areaCode=00&deptCode=000&liCode=0000

標題: 【Data Reporter】35張圖表,帶你看2024大選關鍵結果
描述: 2024年1月15日 —
網址: https://www.twreporter.org/a/2024-election-results-chart

結果與上面是一樣的. 

在 SerpAPI 儀錶板網頁右上角會記錄已呼叫 API 的次數, 免費帳戶每月可呼叫 100 次 : 



沒有留言 :