.oO SearXNG Developer Documentation Oo.
Loading...
Searching...
No Matches
chinaso.py
Go to the documentation of this file.
1# SPDX-License-Identifier: AGPL-3.0-or-later
2"""ChinaSo_, a search engine for the chinese language area.
3
4.. attention::
5
6 ChinaSo engine does not return real URL, the links from these search
7 engines violate the privacy of the users!!
8
9 We try to find a solution for this problem, please follow `issue #4694`_.
10
11 As long as the problem has not been resolved, these engines are
12 not active in a standard setup (``inactive: true``).
13
14.. _ChinaSo: https://www.chinaso.com/
15.. _issue #4694: https://github.com/searxng/searxng/issues/4694
16
17Configuration
18=============
19
20The engine has the following additional settings:
21
22- :py:obj:`chinaso_category` (:py:obj:`ChinasoCategoryType`)
23- :py:obj:`chinaso_news_source` (:py:obj:`ChinasoNewsSourceType`)
24
25In the example below, all three ChinaSO engines are using the :ref:`network
26<engine network>` from the ``chinaso news`` engine.
27
28.. code:: yaml
29
30 - name: chinaso news
31 engine: chinaso
32 shortcut: chinaso
33 categories: [news]
34 chinaso_category: news
35 chinaso_news_source: all
36
37 - name: chinaso images
38 engine: chinaso
39 network: chinaso news
40 shortcut: chinasoi
41 categories: [images]
42 chinaso_category: images
43
44 - name: chinaso videos
45 engine: chinaso
46 network: chinaso news
47 shortcut: chinasov
48 categories: [videos]
49 chinaso_category: videos
50
51
52Implementations
53===============
54
55"""
56
57import typing
58
59from urllib.parse import urlencode
60from datetime import datetime
61
62from searx.exceptions import SearxEngineAPIException
63from searx.utils import html_to_text
64
65about = {
66 "website": "https://www.chinaso.com/",
67 "wikidata_id": "Q10846064",
68 "use_official_api": False,
69 "require_api_key": False,
70 "results": "JSON",
71 "language": "zh",
72}
73
74paging = True
75time_range_support = True
76results_per_page = 10
77categories = []
78
79ChinasoCategoryType = typing.Literal['news', 'videos', 'images']
80"""ChinaSo supports news, videos, images search.
81
82- ``news``: search for news
83- ``videos``: search for videos
84- ``images``: search for images
85
86In the category ``news`` you can additionally filter by option
87:py:obj:`chinaso_news_source`.
88"""
89chinaso_category = 'news'
90"""Configure ChinaSo category (:py:obj:`ChinasoCategoryType`)."""
91
92ChinasoNewsSourceType = typing.Literal['CENTRAL', 'LOCAL', 'BUSINESS', 'EPAPER', 'all']
93"""Filtering ChinaSo-News results by source:
94
95- ``CENTRAL``: central publication
96- ``LOCAL``: local publication
97- ``BUSINESS``: business publication
98- ``EPAPER``: E-Paper
99- ``all``: all sources
100"""
101chinaso_news_source: ChinasoNewsSourceType = 'all'
102"""Configure ChinaSo-News type (:py:obj:`ChinasoNewsSourceType`)."""
103
104time_range_dict = {'day': '24h', 'week': '1w', 'month': '1m', 'year': '1y'}
105
106base_url = "https://www.chinaso.com"
107
108
109def init(_):
110 if chinaso_category not in ('news', 'videos', 'images'):
111 raise ValueError(f"Unsupported category: {chinaso_category}")
112 if chinaso_category == 'news' and chinaso_news_source not in typing.get_args(ChinasoNewsSourceType):
113 raise ValueError(f"Unsupported news source: {chinaso_news_source}")
114
115
116def request(query, params):
117 query_params = {"q": query}
118
119 if time_range_dict.get(params['time_range']):
120 query_params["stime"] = time_range_dict[params['time_range']]
121 query_params["etime"] = 'now'
122
123 category_config = {
124 'news': {'endpoint': '/v5/general/v1/web/search', 'params': {'pn': params["pageno"], 'ps': results_per_page}},
125 'images': {
126 'endpoint': '/v5/general/v1/search/image',
127 'params': {'start_index': (params["pageno"] - 1) * results_per_page, 'rn': results_per_page},
128 },
129 'videos': {
130 'endpoint': '/v5/general/v1/search/video',
131 'params': {'start_index': (params["pageno"] - 1) * results_per_page, 'rn': results_per_page},
132 },
133 }
134 if chinaso_news_source != 'all':
135 if chinaso_news_source == 'EPAPER':
136 category_config['news']['params']["type"] = 'EPAPER'
137 else:
138 category_config['news']['params']["cate"] = chinaso_news_source
139
140 query_params.update(category_config[chinaso_category]['params'])
141
142 params["url"] = f"{base_url}{category_config[chinaso_category]['endpoint']}?{urlencode(query_params)}"
143
144 return params
145
146
147def response(resp):
148 try:
149 data = resp.json()
150 except Exception as e:
151 raise SearxEngineAPIException(f"Invalid response: {e}") from e
152
153 parsers = {'news': parse_news, 'images': parse_images, 'videos': parse_videos}
154
155 return parsers[chinaso_category](data)
156
157
158def parse_news(data):
159 results = []
160 if not data.get("data", {}).get("data"):
161 raise SearxEngineAPIException("Invalid response")
162
163 for entry in data["data"]["data"]:
164 published_date = None
165 if entry.get("timestamp"):
166 try:
167 published_date = datetime.fromtimestamp(int(entry["timestamp"]))
168 except (ValueError, TypeError):
169 pass
170
171 results.append(
172 {
173 'title': html_to_text(entry["title"]),
174 'url': entry["url"],
175 'content': html_to_text(entry["snippet"]),
176 'publishedDate': published_date,
177 }
178 )
179 return results
180
181
182def parse_images(data):
183 results = []
184 if not data.get("data", {}).get("arrRes"):
185 raise SearxEngineAPIException("Invalid response")
186
187 for entry in data["data"]["arrRes"]:
188 results.append(
189 {
190 'url': entry["web_url"],
191 'title': html_to_text(entry["title"]),
192 'content': html_to_text(entry["ImageInfo"]),
193 'template': 'images.html',
194 'img_src': entry["url"].replace("http://", "https://"),
195 'thumbnail_src': entry["largeimage"].replace("http://", "https://"),
196 }
197 )
198 return results
199
200
201def parse_videos(data):
202 results = []
203 if not data.get("data", {}).get("arrRes"):
204 raise SearxEngineAPIException("Invalid response")
205
206 for entry in data["data"]["arrRes"]:
207 published_date = None
208 if entry.get("VideoPubDate"):
209 try:
210 published_date = datetime.fromtimestamp(int(entry["VideoPubDate"]))
211 except (ValueError, TypeError):
212 pass
213
214 results.append(
215 {
216 'url': entry["url"],
217 'title': html_to_text(entry["raw_title"]),
218 'template': 'videos.html',
219 'publishedDate': published_date,
220 'thumbnail': entry["image_src"].replace("http://", "https://"),
221 }
222 )
223 return results
request(query, params)
Definition chinaso.py:116