@@ -10,35 +10,50 @@ Definitions`_.
1010 ``data:` scheme).::
1111
1212 Header set Content-Security-Policy "img-src 'self' data: ;"
13+
14+.. _Query Parameter Definitions:
15+ https://developers.google.com/custom-search/docs/xml_results#WebSearch_Query_Parameter_Definitions
16+.. _data URLs:
17+ https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
1318"""
1419
1520from urllib.parse import urlencode, unquote
1621from lxml import html
22+
1723from searx import logger
18−from searx.utils import extract_text, eval_xpath
19−from searx.engines.google import _fetch_supported_languages, supported_languages_url # NOQA # pylint: disable=unused-import
24+from searx.utils import (
25+ eval_xpath,
26+ eval_xpath_list,
27+ eval_xpath_getindex,
28+ extract_text,
29+)
2030
2131from searx.engines.google import (
22− get_lang_country,
23− google_domains,
32+ get_lang_info,
2433 time_range_dict,
2534 detect_google_sorry,
2635)
2736
37+# pylint: disable=unused-import
38+from searx.engines.google import (
39+ supported_languages_url
40+ , _fetch_supported_languages
41+)
42+# pylint: enable=unused-import
43+
2844logger = logger.getChild('google images')
2945
3046# about
3147about = {
32− "website": 'https://images.google.com/',
48+ "website": 'https://images.google.com',
3349 "wikidata_id": 'Q521550',
34− "official_api_documentation": 'https://developers.google.com/custom-search/docs/xml_results#WebSearch_Query_Parameter_Definitions', # NOQA
50+ "official_api_documentation": 'https://developers.google.com/custom-search',
3551 "use_official_api": False,
3652 "require_api_key": False,
3753 "results": 'HTML',
3854}
3955
4056# engine dependent config
41−
4257categories = ['images']
4358paging = False
4459language_support = True
@@ -84,17 +99,16 @@ def scrap_img_by_id(script, data_id):
8499def request(query, params):
85100 """Google-Video search request"""
86101
87− language, country, lang_country = get_lang_country(
102+ lang_info = get_lang_info(
88103 # pylint: disable=undefined-variable
89104 params, supported_languages, language_aliases
90105 )
91− subdomain = 'www.' + google_domains.get(country.upper(), 'google.com')
92106
93− query_url = 'https://' + subdomain + '/search' + "?" + urlencode({
107+ query_url = 'https://' + lang_info['subdomain'] + '/search' + "?" + urlencode({
94108 'q': query,
95109 'tbm': "isch",
96− 'hl': lang_country,
97− 'lr': "lang_" + language,
110+ 'hl': lang_info['hl'],
111+ 'lr': lang_info['lr'],
98112 'ie': "utf8",
99113 'oe': "utf8",
100114 'num': 30,
@@ -105,17 +119,14 @@ def request(query, params):
105119 if params['safesearch']:
106120 query_url += '&' + urlencode({'safe': filter_mapping[params['safesearch']]})
107121
108− params['url'] = query_url
109122 logger.debug("query_url --> %s", query_url)
123+ params['url'] = query_url
110124
111− params['headers']['Accept-Language'] = (
112− "%s,%s;q=0.8,%s;q=0.5" % (lang_country, language, language))
113− logger.debug(
114− "HTTP Accept-Language --> %s", params['headers']['Accept-Language'])
125+ logger.debug("HTTP header Accept-Language --> %s", lang_info['Accept-Language'])
126+ params['headers']['Accept-Language'] = lang_info['Accept-Language']
115127 params['headers']['Accept'] = (
116128 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
117129 )
118− # params['google_subdomain'] = subdomain
119130 return params
120131
121132
@@ -125,13 +136,11 @@ def response(resp):
125136
126137 detect_google_sorry(resp)
127138
128− # which subdomain ?
129− # subdomain = resp.search_params.get('google_subdomain')
130−
131139 # convert the text to dom
132140 dom = html.fromstring(resp.text)
133141 img_bas64_map = scrap_out_thumbs(dom)
134− img_src_script = eval_xpath(dom, '//script[contains(., "AF_initDataCallback({key: ")]')[1].text
142+ img_src_script = eval_xpath_getindex(
143+ dom, '//script[contains(., "AF_initDataCallback({key: ")]', 1).text
135144
136145 # parse results
137146 #
@@ -156,55 +165,47 @@ def response(resp):
156165 return results
157166
158167 root = root[0]
159− for img_node in eval_xpath(root, './/img[contains(@class, "rg_i")]'):
160−
161− try:
162− img_alt = eval_xpath(img_node, '@alt')[0]
163−
164− img_base64_id = eval_xpath(img_node, '@data-iid')
165− if img_base64_id:
166− img_base64_id = img_base64_id[0]
167− thumbnail_src = img_bas64_map[img_base64_id]
168+ for img_node in eval_xpath_list(root, './/img[contains(@class, "rg_i")]'):
169+
170+ img_alt = eval_xpath_getindex(img_node, '@alt', 0)
171+
172+ img_base64_id = eval_xpath(img_node, '@data-iid')
173+ if img_base64_id:
174+ img_base64_id = img_base64_id[0]
175+ thumbnail_src = img_bas64_map[img_base64_id]
176+ else:
177+ thumbnail_src = eval_xpath(img_node, '@src')
178+ if not thumbnail_src:
179+ thumbnail_src = eval_xpath(img_node, '@data-src')
180+ if thumbnail_src:
181+ thumbnail_src = thumbnail_src[0]
168182 else:
169− thumbnail_src = eval_xpath(img_node, '@src')
170− if not thumbnail_src:
171− thumbnail_src = eval_xpath(img_node, '@data-src')
172− if thumbnail_src:
173− thumbnail_src = thumbnail_src[0]
174− else:
175− thumbnail_src = ''
176−
177− link_node = eval_xpath(img_node, '../../../a[2]')[0]
178− url = eval_xpath(link_node, '@href')[0]
179−
180− pub_nodes = eval_xpath(link_node, './div/div')
181− pub_descr = img_alt
182− pub_source = ''
183− if pub_nodes:
184− pub_descr = extract_text(pub_nodes[0])
185− pub_source = extract_text(pub_nodes[1])
186−
187− img_src_id = eval_xpath(img_node, '../../../@data-id')[0]
188− src_url = scrap_img_by_id(img_src_script, img_src_id)
189− if not src_url:
190− src_url = thumbnail_src
191−
192− results.append({
193− 'url': url,
194− 'title': img_alt,
195− 'content': pub_descr,
196− 'source': pub_source,
197− 'img_src': src_url,
198− # 'img_format': img_format,
199− 'thumbnail_src': thumbnail_src,
200− 'template': 'images.html'
201− })
202− except Exception as e: # pylint: disable=broad-except
203− logger.error(e, exc_info=True)
204− # from lxml import etree
205− # logger.debug(etree.tostring(img_node, pretty_print=True))
206− # import pdb
207− # pdb.set_trace()
208− continue
183+ thumbnail_src = ''
184+
185+ link_node = eval_xpath_getindex(img_node, '../../../a[2]', 0)
186+ url = eval_xpath_getindex(link_node, '@href', 0)
187+
188+ pub_nodes = eval_xpath(link_node, './div/div')
189+ pub_descr = img_alt
190+ pub_source = ''
191+ if pub_nodes:
192+ pub_descr = extract_text(pub_nodes[0])
193+ pub_source = extract_text(pub_nodes[1])
194+
195+ img_src_id = eval_xpath_getindex(img_node, '../../../@data-id', 0)
196+ src_url = scrap_img_by_id(img_src_script, img_src_id)
197+ if not src_url:
198+ src_url = thumbnail_src
199+
200+ results.append({
201+ 'url': url,
202+ 'title': img_alt,
203+ 'content': pub_descr,
204+ 'source': pub_source,
205+ 'img_src': src_url,
206+ # 'img_format': img_format,
207+ 'thumbnail_src': thumbnail_src,
208+ 'template': 'images.html'
209+ })
209210
210211 return results