From b64e6ee44a8536d84dd8446e8f947dd418c265b2 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sun, 5 Jul 2026 13:40:50 +0200 Subject: [PATCH] [feat] google CSE engine: add support for images (#6369) Add support for Google CSE images, the normal google images engine doesn't work anymore, so this is a good workaround for now. --- searx/engines/google_cse.py | 60 +++++++++++++++++++++++++++++-------- searx/settings.yml | 15 +++++++--- 2 files changed, 59 insertions(+), 16 deletions(-) diff --git a/searx/engines/google_cse.py b/searx/engines/google_cse.py index a0261e324..4c333dfdd 100644 --- a/searx/engines/google_cse.py +++ b/searx/engines/google_cse.py @@ -9,7 +9,7 @@ from urllib.parse import urlencode from searx.enginelib import EngineCache from searx.exceptions import SearxEngineAPIException, SearxEngineTooManyRequestsException from searx.network import get -from searx.result_types import EngineResults +from searx.result_types import EngineResults, Result, MainResult, Image from searx.engines.google import fetch_traits # pylint: disable=unused-import from searx.engines.google import filter_mapping, get_google_info @@ -36,6 +36,10 @@ time_range_support = True language_support = True safesearch = True +GoogleCategType = t.Literal["", "image"] +google_categ: GoogleCategType = "" +"""Google CSE category. Set to ``""`` for web search.""" + CX = "partner-pub-8993703457585266:4862972284" # blackle.com CACHE: EngineCache @@ -43,6 +47,10 @@ CACHE: EngineCache def setup(engine_settings: dict[str, t.Any]) -> bool: global CACHE # pylint: disable=global-statement + + if google_categ not in t.get_args(GoogleCategType): + raise ValueError("invalid google cse category: %s" % google_categ) + CACHE = EngineCache(engine_settings["name"]) return True @@ -104,6 +112,7 @@ def request(query: str, params: "OnlineParams") -> None: "cse_tok": token["cse_tok"], "callback": "_", "rurl": "", + "searchtype": google_categ, } if params["time_range"]: start_date, end_date = _get_start_and_end_date_str(params["time_range"]) @@ -143,16 +152,43 @@ def response(resp: "SXNG_Response") -> EngineResults: raise SearxEngineAPIException(f"google cse: {message}") results = EngineResults() + for item in data.get("results", []): - url = item.get("unescapedUrl") - if not url: - continue - results.add( - results.types.MainResult( - url=url, - title=item.get("titleNoFormatting", ""), - content=item.get("contentNoFormatting", ""), - thumbnail=item.get("richSnippet", {}).get("cseThumbnail", {}).get("src", ""), # type: ignore - ) - ) + + res: Result | None + if google_categ == "": + res = web_item(item) + elif google_categ == "image": + res = img_item(item) + + if res is not None: + results.add(res) + return results + + +def web_item(item: dict[str, str]) -> MainResult | None: + url = item.get("unescapedUrl") + if not url: + return None + return MainResult( + url=url, + title=item.get("titleNoFormatting", ""), + content=item.get("contentNoFormatting", ""), + thumbnail=item.get("richSnippet", {}).get("cseThumbnail", {}).get("src", ""), # type: ignore + ) + + +def img_item(item: dict[str, str]) -> Image | None: + resolution = "" + if item.get("height") and item.get("width"): + resolution = f"{item['width']}x{item['height']}" + return Image( + url=item["originalContextUrl"], + title=item.get("titleNoFormatting", ""), + content=item.get("contentNoFormatting", ""), + img_src=item["unescapedUrl"], + thumbnail_src=item["tbUrl"], + resolution=resolution, + img_format=item["fileFormat"].split("/")[-1], + ) diff --git a/searx/settings.yml b/searx/settings.yml index 977b66852..d2003a532 100644 --- a/searx/settings.yml +++ b/searx/settings.yml @@ -1201,13 +1201,10 @@ engines: shortcut: go inactive: true - - name: google cse - engine: google_cse - shortcut: goc - - name: google images engine: google_images shortcut: goi + inactive: true - name: google news engine: google_news @@ -1218,6 +1215,16 @@ engines: shortcut: gov inactive: true + - name: google cse + engine: google_cse + shortcut: goc + + - name: google cse images + engine: google_cse + categories: [images, web] + google_categ: image + shortcut: goci + - name: google scholar engine: google_scholar shortcut: gos