summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/dev/engines/online/jina.rst8
-rw-r--r--searx/engines/jina.py89
-rw-r--r--searx/settings.yml6
3 files changed, 103 insertions, 0 deletions
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 <https://jina.ai/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]