From 0a118066d8565c0cf80fbc5ea90f20c875bbcfe6 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Wed, 5 Aug 2026 18:49:33 +0200 Subject: [PATCH] [feat] engines: add jina (general) --- docs/dev/engines/online/jina.rst | 8 +++ searx/engines/jina.py | 89 ++++++++++++++++++++++++++++++++ searx/settings.yml | 6 +++ 3 files changed, 103 insertions(+) create mode 100644 docs/dev/engines/online/jina.rst create mode 100644 searx/engines/jina.py diff --git a/docs/dev/engines/online/jina.rst b/docs/dev/engines/online/jina.rst new file mode 100644 index 000000000..118a358d4 --- /dev/null +++ b/docs/dev/engines/online/jina.rst @@ -0,0 +1,8 @@ +.. _jina engine: + +=========== +Jina Engine +=========== + +.. automodule:: searx.engines.jina + :members: diff --git a/searx/engines/jina.py b/searx/engines/jina.py new file mode 100644 index 000000000..24ecaa51d --- /dev/null +++ b/searx/engines/jina.py @@ -0,0 +1,89 @@ +# SPDX-License-Identifier: AGPL-3.0-or-later +"""Jina is a search AI and part of Elastic, the company behind ElasticSearch. + +The engine requires an API key, you can get one from the +`API dashboard `_ without signup. + +.. code:: yaml + + - name: jina + engine: jina + shortcut: ji + api_key: "jina_..." + jina_engine: reader + inactive: false + +By default, Jina's own index is used. You can change that by setting a different :py:obj:`jina_engine`. +""" + +import typing as t +from urllib.parse import urlencode + +from dateutil import parser +from searx.result_types import EngineResults + +if t.TYPE_CHECKING: + from searx.extended_types import SXNG_Response + from searx.search.processors import OnlineParams + + +about = { + "website": "https://jina.ai", + "wikidata_id": None, + "official_api_documentation": "https://s.jina.ai/docs", + "use_official_api": True, + "require_api_key": True, + "results": "JSON", +} + +categories = ["general"] +paging = True + +jina_engine = "reader" +"""Search mode. Currently supported values are 'reader', 'google' and 'bing'.""" + +base_url = "https://s.jina.ai" +api_key: str | None = None + + +def setup(_): + if not api_key: + raise ValueError("missing api key") + + +def request(query: str, params: "OnlineParams"): + # setting 'no-content' pushes the response time down to a third + args = {"q": query, "page": params["pageno"], "engine": jina_engine, "respondWith": "no-content"} + params["url"] = f"{base_url}/?{urlencode(args)}" + params["headers"].update( + { + "Accept": "application/json", + "Authorization": f"Bearer {api_key}", + } + ) + + +def response(resp: "SXNG_Response"): + res = EngineResults() + + json_resp: dict[str, t.Any] = resp.json() + + result: dict[str, str] + for result in json_resp["data"]: + published_date = None + if result.get("date"): + try: + published_date = parser.parse(result["date"]) + except parser.ParserError: + pass + + res.add( + res.types.MainResult( + url=result["url"], + title=result["title"], + content=result["description"], + publishedDate=published_date, + ) + ) + + return res diff --git a/searx/settings.yml b/searx/settings.yml index e8c540d12..1650a484d 100644 --- a/searx/settings.yml +++ b/searx/settings.yml @@ -1411,6 +1411,12 @@ engines: shortcut: iq disabled: true + - name: jina + engine: jina + shortcut: ji + api_key: "" + inactive: true + # - name: kagi # engine: kagi # categories: [general, web]