.oO SearXNG Developer Documentation Oo.
Loading...
Searching...
No Matches
adobe_stock.py
Go to the documentation of this file.
1
# SPDX-License-Identifier: AGPL-3.0-or-later
2
"""`Adobe Stock`_ is a service that gives access to millions of royalty-free
3
assets. Assets types include photos, vectors, illustrations, templates, 3D
4
assets, videos, motion graphics templates and audio tracks.
5
6
.. Adobe Stock: https://stock.adobe.com/
7
8
Configuration
9
=============
10
11
The engine has the following mandatory setting:
12
13
- SearXNG's :ref:`engine categories`
14
- Adobe-Stock's :py:obj:`adobe_order`
15
- Adobe-Stock's :py:obj:`adobe_content_types`
16
17
.. code:: yaml
18
19
- name: adobe stock
20
engine: adobe_stock
21
shortcut: asi
22
categories: [images]
23
adobe_order: relevance
24
adobe_content_types: ["photo", "illustration", "zip_vector", "template", "3d", "image"]
25
26
- name: adobe stock video
27
engine: adobe_stock
28
network: adobe stock
29
shortcut: asi
30
categories: [videos]
31
adobe_order: relevance
32
adobe_content_types: ["video"]
33
34
Implementation
35
==============
36
37
"""
38
39
from
datetime
import
datetime, timedelta
40
from
urllib.parse
import
urlencode
41
42
import
isodate
43
44
about = {
45
"website"
:
"https://stock.adobe.com/"
,
46
"wikidata_id"
:
"Q5977430"
,
47
"official_api_documentation"
:
None
,
48
"use_official_api"
:
False
,
49
"require_api_key"
:
False
,
50
"results"
:
"JSON"
,
51
}
52
53
categories = []
54
paging =
True
55
send_accept_language_header =
True
56
results_per_page = 10
57
58
base_url =
"https://stock.adobe.com"
59
60
adobe_order: str =
""
61
"""Sort order, can be one of:
62
63
- ``relevance`` or
64
- ``featured`` or
65
- ``creation`` (most recent) or
66
- ``nb_downloads`` (number of downloads)
67
"""
68
69
ADOBE_VALID_TYPES = [
"photo"
,
"illustration"
,
"zip_vector"
,
"video"
,
"template"
,
"3d"
,
"audio"
,
"image"
]
70
adobe_content_types: list = []
71
"""A list of of content types. The following content types are offered:
72
73
- Images: ``image``
74
- Videos: ``video``
75
- Templates: ``template``
76
- 3D: ``3d``
77
- Audio ``audio``
78
79
Additional subcategories:
80
81
- Photos: ``photo``
82
- Illustrations: ``illustration``
83
- Vectors: ``zip_vector`` (Vectors),
84
"""
85
86
# Do we need support for "free_collection" and "include_stock_enterprise"?
87
88
89
def
init
(_):
90
if
not
categories:
91
raise
ValueError(
"adobe_stock engine: categories is unset"
)
92
93
# adobe_order
94
if
not
adobe_order:
95
raise
ValueError(
"adobe_stock engine: adobe_order is unset"
)
96
if
adobe_order
not
in
[
"relevance"
,
"featured"
,
"creation"
,
"nb_downloads"
]:
97
raise
ValueError(f
"unsupported adobe_order: {adobe_order}"
)
98
99
# adobe_content_types
100
if
not
adobe_content_types:
101
raise
ValueError(
"adobe_stock engine: adobe_content_types is unset"
)
102
103
if
isinstance(adobe_content_types, list):
104
for
t
in
adobe_content_types:
105
if
t
not
in
ADOBE_VALID_TYPES:
106
raise
ValueError(
"adobe_stock engine: adobe_content_types: '%s' is invalid"
% t)
107
else
:
108
raise
ValueError(
109
"adobe_stock engine: adobe_content_types must be a list of strings not %s"
% type(adobe_content_types)
110
)
111
112
113
def
request
(query, params):
114
115
args = {
116
"k"
: query,
117
"limit"
: results_per_page,
118
"order"
: adobe_order,
119
"search_page"
: params[
"pageno"
],
120
"search_type"
:
"pagination"
,
121
}
122
123
for
content_type
in
ADOBE_VALID_TYPES:
124
args[f
"filters[content_type:{content_type}]"
] = 1
if
content_type
in
adobe_content_types
else
0
125
126
params[
"url"
] = f
"{base_url}/de/Ajax/Search?{urlencode(args)}"
127
128
# headers required to bypass bot-detection
129
if
params[
"searxng_locale"
] ==
"all"
:
130
params[
"headers"
][
"Accept-Language"
] =
"en-US,en;q=0.5"
131
132
return
params
133
134
135
def
parse_image_item
(item):
136
return
{
137
"template"
:
"images.html"
,
138
"url"
: item[
"content_url"
],
139
"title"
: item[
"title"
],
140
"content"
: item[
"asset_type"
],
141
"img_src"
: item[
"content_thumb_extra_large_url"
],
142
"thumbnail_src"
: item[
"thumbnail_url"
],
143
"resolution"
: f
"{item['content_original_width']}x{item['content_original_height']}"
,
144
"img_format"
: item[
"format"
],
145
"author"
: item[
"author"
],
146
}
147
148
149
def
parse_video_item
(item):
150
151
# in video items, the title is more or less a "content description", we try
152
# to reduce the length of the title ..
153
154
title = item[
"title"
]
155
content =
""
156
if
"."
in
title.strip()[:-1]:
157
content = title
158
title = title.split(
"."
, 1)[0]
159
elif
","
in
title:
160
content = title
161
title = title.split(
","
, 1)[0]
162
elif
len(title) > 50:
163
content = title
164
title =
""
165
for
w
in
content.split(
" "
):
166
title += f
" {w}"
167
if
len(title) > 50:
168
title = title.strip() +
"\u2026"
169
break
170
171
return
{
172
"template"
:
"videos.html"
,
173
"url"
: item[
"content_url"
],
174
"title"
: title,
175
"content"
: content,
176
# https://en.wikipedia.org/wiki/ISO_8601#Durations
177
"length"
: isodate.parse_duration(item[
"time_duration"
]),
178
"publishedDate"
: datetime.fromisoformat(item[
"creation_date"
]),
179
"thumbnail"
: item[
"thumbnail_url"
],
180
"iframe_src"
: item[
"video_small_preview_url"
],
181
"metadata"
: item[
"asset_type"
],
182
}
183
184
185
def
parse_audio_item
(item):
186
audio_data = item[
"audio_data"
]
187
content = audio_data.get(
"description"
)
or
""
188
if
audio_data.get(
"album"
):
189
content = audio_data[
"album"
] +
" - "
+ content
190
191
return
{
192
"url"
: item[
"content_url"
],
193
"title"
: item[
"title"
],
194
"content"
: content,
195
# "thumbnail": base_url + item["thumbnail_url"],
196
"iframe_src"
: audio_data[
"preview"
][
"url"
],
197
"publishedDate"
: datetime.fromisoformat(audio_data[
"release_date"
])
if
audio_data[
"release_date"
]
else
None
,
198
"length"
: timedelta(seconds=round(audio_data[
"duration"
] / 1000))
if
audio_data[
"duration"
]
else
None
,
199
"author"
: item.get(
"artist_name"
),
200
}
201
202
203
def
response
(resp):
204
results = []
205
206
json_resp = resp.json()
207
208
if
isinstance(json_resp[
"items"
], list):
209
return
None
210
for
item
in
json_resp[
"items"
].values():
211
if
item[
"asset_type"
].lower()
in
[
"image"
,
"premium-image"
,
"illustration"
,
"vector"
]:
212
result =
parse_image_item
(item)
213
elif
item[
"asset_type"
].lower() ==
"video"
:
214
result =
parse_video_item
(item)
215
elif
item[
"asset_type"
].lower() ==
"audio"
:
216
result =
parse_audio_item
(item)
217
else
:
218
logger.error(
"no handle for %s --> %s"
, item[
"asset_type"
], item)
219
continue
220
results.append(result)
221
222
return
results
searx.engines.adobe_stock.request
request(query, params)
Definition
adobe_stock.py:113
searx.engines.adobe_stock.parse_image_item
parse_image_item(item)
Definition
adobe_stock.py:135
searx.engines.adobe_stock.response
response(resp)
Definition
adobe_stock.py:203
searx.engines.adobe_stock.parse_video_item
parse_video_item(item)
Definition
adobe_stock.py:149
searx.engines.adobe_stock.init
init(_)
Definition
adobe_stock.py:89
searx.engines.adobe_stock.parse_audio_item
parse_audio_item(item)
Definition
adobe_stock.py:185
searxng
searx
engines
adobe_stock.py
Generated on
for .oO SearXNG Developer Documentation Oo. by
1.14.0