首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 訪問 Google Search API:Custom Search JSON API 完整整合指南

     編輯:PHP 相關知識

Google 官方搜尋 API 為 Custom Search JSON API,提供每日 100 次免費查詢,適合建立站內搜尋、關鍵字排名監控、內容聚合等功能。本文說明申請流程、PHP 整合代碼、配額管理、錯誤處理。

前置準備

  1. Google Cloud 專案:建立專案
  2. 啟用 API:「API 和服務」→「程式庫」→搜尋「Custom Search API」→啟用
  3. 建立憑證:「憑證」→「建立憑證」→「API 金鑰」→複製 API_KEY
  4. 建立自訂搜尋引擎:Programmable Search Engine → 新增引擎 → 設定搜尋範圍(全網或指定網站)→ 取得 CX (搜尋引擎 ID)
  5. 計費帳戶:免費額度 100 次/天,超過需關聯計費帳戶($5/1000 次)

PHP 整合類

<?php
namespace App\Service;

class GoogleCustomSearch {
    private const ENDPOINT = 'https://www.googleapis.com/customsearch/v1';
    private string $apiKey;
    private string $cx;
    private int $timeout = 10;

    public function __construct(string $apiKey, string $cx) {
        $this->apiKey = $apiKey;
        $this->cx = $cx;
    }

    /**
     * 執行搜尋
     * @param string $query 搜尋關鍵字
     * @param array  $options 額外參數:num(結果數 1-10), start(起始索引 1-91), lr(語言), gl(地區), safe(安全搜尋), dateRestrict(日期限制), fileType(檔案類型), siteSearch(限定網站), siteSearchFilter(i/e)
     * @return array ['items' => [], 'totalResults' => int, 'searchTime' => float]
     * @throws RuntimeException
     */
    public function search(string $query, array $options = []): array {
        $params = array_merge([
            'key'   => $this->apiKey,
            'cx'    => $this->cx,
            'q'     => $query,
            'num'   => 10,      // 每頁最多 10 筆
            'start' => 1,       // 起始索引
        ], $options);

        $url = self::ENDPOINT . '?' . http_build_query($params);

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => $this->timeout,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_SSL_VERIFYHOST => 2,
            CURLOPT_USERAGENT      => 'MyApp/1.0 (+https://example.com)',
            CURLOPT_HTTPHEADER     => [
                'Accept: application/json',
            ],
        ]);

        $response = curl_exec($ch);
        $errno = curl_errno($ch);
        $error = curl_error($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($errno) {
            throw new RuntimeException("cURL 錯誤 ({$errno}): {$error}");
        }

        if ($httpCode !== 200) {
            $body = $response ?: '無回應內容';
            throw new RuntimeException("HTTP {$httpCode}: {$body}");
        }

        $data = json_decode($response, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new RuntimeException('JSON 解析失敗: ' . json_last_error_msg());
        }

        // API 錯誤回應格式
        if (isset($data['error'])) {
            $err = $data['error'];
            throw new RuntimeException("API 錯誤 [{$err['code']}]: {$err['message']} (" . ($err['errors'][0]['reason'] ?? '') . ")");
        }

        return [
            'items'         => $data['items'] ?? [],
            'totalResults'  => (int)($data['searchInformation']['totalResults'] ?? 0),
            'searchTime'    => (float)($data['searchInformation']['searchTime'] ?? 0),
            'queries'       => $data['queries'] ?? [],
        ];
    }

    /** 分頁搜尋:自動處理 start 參數,最多 10 頁 (100 筆) */
    public function searchAll(string $query, int $maxPages = 10): array {
        $allItems = [];
        for ($page = 1; $page <= $maxPages; $page++) {
            $start = ($page - 1) * 10 + 1;
            $result = $this->search($query, ['start' => $start, 'num' => 10]);
            $allItems = array_merge($allItems, $result['items']);
            if (count($result['items']) < 10) break; // 無更多結果
            // 避免觸發速率限制
            usleep(200000); // 200ms
        }
        return [
            'items' => $allItems,
            'total' => count($allItems),
        ];
    }
}
?>

使用範例

<?php
require 'vendor/autoload.php';
use App\Service\GoogleCustomSearch;

$apiKey = 'YOUR_API_KEY';
$cx     = 'YOUR_SEARCH_ENGINE_ID'; // 格式類似 0123456789abcdef:abcdefghijk

$search = new GoogleCustomSearch($apiKey, $cx);

try {
    // 基本搜尋
    $result = $search->search('PHP 8.2 新特性', [
        'num'   => 10,
        'lr'    => 'lang_zh-TW', // 繁體中文
        'gl'    => 'tw',         // 台灣地區
        'safe'  => 'active',     // 安全搜尋
    ]);

    echo "找到 {$result['totalResults']} 筆結果,耗時 {$result['searchTime']} 秒\n";
    foreach ($result['items'] as $item) {
        echo "標題: {$item['title']}\n";
        echo "連結: {$item['link']}\n";
        echo "摘要: {$item['snippet']}\n";
        echo "---\n";
    }

    // 限定站內搜尋
    $siteResult = $search->search('Laravel 教學', [
        'siteSearch' => 'example.com',
        'siteSearchFilter' => 'i', // i=包含, e=排除
    ]);

    // 分頁獲取前 50 筆
    $all = $search->searchAll('Composer 套件推薦', 5);
    echo "共獲取 {$all['total']} 筆\n";

} catch (RuntimeException $e) {
    echo "搜尋失敗: {$e->getMessage()}\n";
    // 常見錯誤代碼:
    // 400: 參數錯誤 (key, cx, q 必填)
    // 403: 配額用盡、API 未啟用、金鑰限制
    // 429: 請求過於頻繁

關鍵參數說明

配額與限制管理

  • 免費額度:100 次查詢/天/專案
  • 付費額度:$5/1000 次,需啟用計費
  • 速率限制:約 5 QPS (每秒查詢數),超過返回 429
  • 結果限制:單次最多 10 筆,分頁最多 10 頁 (100 筆)
  • 快取策略:相同查詢結果快取 1-24 小時,減少 API 呼叫

錯誤代碼對照與處理

參數說明範例
q搜尋查詢字串,支援 Google 搜尋運算子site:github.com PHP
num每頁結果數 (1-10)10
start起始索引 (1, 11, 21... 最大 91)11 (第 2 頁)
lr語言限制lang_zh-TW, lang_en
gl地區限制 (國家代碼)tw, us, hk
safe安全搜尋active (過濾), off (關閉)
dateRestrict日期限制d7 (7天內), m1 (1個月內), y1 (1年內)
fileType檔案類型pdf, doc, ppt
siteSearch限定搜尋網站example.com
siteSearchFilteri (包含) / e (排除)i
HTTP 代碼錯誤原因處理建議
400參數無效 (缺 key/cx/q、參數格式錯誤)檢查請求參數、URL 編碼
403配額用盡、API 未啟用、API 金鑰限制 (HTTP Referrer、IP、應用限制)Cloud Console 檢查配額、啟用 API、調整金鑰限制
429請求過於頻繁指數退避重試、增加請求間隔、申請提高配額
500/503Google 伺服器內部錯誤指數退避重試、記錄日誌稍後再試

進階:Guzzle HTTP 客戶端版本 (現代框架推薦)

<?php
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

class GoogleSearchGuzzle {
    private Client $client;
    private string $apiKey;
    private string $cx;

    public function __construct(string $apiKey, string $cx) {
        $this->apiKey = $apiKey;
        $this->cx = $cx;
        $this->client = new Client([
            'base_uri' => 'https://www.googleapis.com/',
            'timeout'  => 10,
            'headers'  => ['Accept' => 'application/json', 'User-Agent' => 'MyApp/1.0'],
        ]);
    }

    public function search(string $query, array $options = []): array {
        $params = array_merge(['key' => $this->apiKey, 'cx' => $this->cx, 'q' => $query], $options);
        try {
            $response = $this->client->get('customsearch/v1', ['query' => $params]);
            $data = json_decode($response->getBody()->getContents(), true);
            if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
            return ['items' => $data['items'] ?? [], 'total' => (int)($data['searchInformation']['totalResults'] ?? 0)];
        } catch (RequestException $e) {
            throw new RuntimeException("請求失敗: {$e->getMessage()}");
        }
    }
}
?>

總結

Google Custom Search JSON API 是整合 Google 搜尋功能的標準方式。關鍵點:

  1. 正確申請 API Key 與 CX (搜尋引擎 ID)
  2. 妥善處理 配額限制 (免費 100/天) 與 速率限制
  3. 使用 Guze/HTTP Client 替代原生 cURL,提升可維護性
  4. 實作 快取、重試、錯誤處理 確保生產穩定
  5. 注意:此 API 非「Google 搜尋完整結果」,僅限自訂搜尋引擎範圍內結果
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved