@@ -1,6 +1,5 @@
1# SPDX-License-Identifier: AGPL-3.0-or-later
1# SPDX-License-Identifier: AGPL-3.0-or-later
3−Google (Viedo)
2+"""Google (Video)
5For detailed description of the *REST-full* API see: `Query Parameter
4For detailed description of the *REST-full* API see: `Query Parameter
6Definitions`_. Not all parameters can be appied.
5Definitions`_. Not all parameters can be appied.
@@ -22,20 +21,19 @@ Definitions`_. Not all parameters can be appied.
22# pylint: disable=invalid-name, missing-function-docstring
21# pylint: disable=invalid-name, missing-function-docstring
25−from urllib.parse import urlencode, urlparse
24+from urllib.parse import urlencode
26from lxml import html
25from lxml import html
28from searx import logger
27from searx import logger
29−from searx.exceptions import SearxEngineCaptchaException
30from searx.utils import (
28from searx.utils import (
31 eval_xpath,
29 eval_xpath,
32 eval_xpath_list,
30 eval_xpath_list,
33 extract_text,
32 extract_text,
36from searx.engines.google import (
35from searx.engines.google import (
37− get_lang_country,
36+ get_lang_info,
39 time_range_dict,
37 time_range_dict,
40 filter_mapping,
38 filter_mapping,
41 results_xpath,
39 results_xpath,
@@ -44,7 +42,8 @@ from searx.engines.google import (
44 href_xpath,
42 href_xpath,
45 content_xpath,
43 content_xpath,
46 suggestion_xpath,
44 suggestion_xpath,
47− spelling_suggestion_xpath
45+ spelling_suggestion_xpath,
50# pylint: disable=unused-import
49# pylint: disable=unused-import
@@ -58,12 +57,10 @@ from searx.engines.google import (
59 "website": 'https://www.google.com',
58 "website": 'https://www.google.com',
60 "wikidata_id": 'Q219885',
59 "wikidata_id": 'Q219885',
61− "official_api_documentation": 'https://developers.google.com/custom-search/',
60+ "official_api_documentation": 'https://developers.google.com/custom-search',
62 "use_official_api": False,
61 "use_official_api": False,
63 "require_api_key": False,
62 "require_api_key": False,
64 "results": 'HTML',
63 "results": 'HTML',
65− "template": 'video.html',
66− "parse": ('url', 'title', 'content', 'thumbnail')
69logger = logger.getChild('google video')
66logger = logger.getChild('google video')
@@ -90,7 +87,7 @@ def scrap_out_thumbs(dom):
90 ret_val = dict()
87 ret_val = dict()
91 thumb_name = 'vidthumb'
88 thumb_name = 'vidthumb'
93− for script in eval_xpath(dom, '//script[contains(., "_setImagesSrc")]'):
90+ for script in eval_xpath_list(dom, '//script[contains(., "_setImagesSrc")]'):
94 _script = script.text
91 _script = script.text
96 # var s='data:image/jpeg;base64, ...'
93 # var s='data:image/jpeg;base64, ...'
@@ -104,7 +101,7 @@ def scrap_out_thumbs(dom):
104 ret_val[_vidthumb] = _imgdata[0].replace(r"\x3d", "=")
101 ret_val[_vidthumb] = _imgdata[0].replace(r"\x3d", "=")
106 # {google.ldidly=-1;google.ldi={"vidthumb8":"https://...
103 # {google.ldidly=-1;google.ldi={"vidthumb8":"https://...
107− for script in eval_xpath(dom, '//script[contains(., "google.ldi={")]'):
104+ for script in eval_xpath_list(dom, '//script[contains(., "google.ldi={")]'):
108 _script = script.text
105 _script = script.text
109 for key_val in _re(r'"%s\d+\":\"[^\"]*"' % thumb_name).findall( _script) :
106 for key_val in _re(r'"%s\d+\":\"[^\"]*"' % thumb_name).findall( _script) :
110 match = _re(r'"(%s\d+)":"(.*)"' % thumb_name).search(key_val)
107 match = _re(r'"(%s\d+)":"(.*)"' % thumb_name).search(key_val)
@@ -119,17 +116,16 @@ def scrap_out_thumbs(dom):
119def request(query, params):
116def request(query, params):
120 """Google-Video search request"""
117 """Google-Video search request"""
122− language, country, lang_country = get_lang_country(
119+ lang_info = get_lang_info(
123 # pylint: disable=undefined-variable
120 # pylint: disable=undefined-variable
124 params, supported_languages, language_aliases
121 params, supported_languages, language_aliases
126− subdomain = 'www.' + google_domains.get(country.upper(), 'google.com')
128− query_url = 'https://'+ subdomain + '/search' + "?" + urlencode({
124+ query_url = 'https://' + lang_info['subdomain'] + '/search' + "?" + urlencode({
129 'q': query,
125 'q': query,
130 'tbm': "vid",
126 'tbm': "vid",
131− 'hl': lang_country,
127+ 'hl': lang_info['hl'],
132− 'lr': "lang_" + language,
128+ 'lr': lang_info['lr'],
133 'ie': "utf8",
129 'ie': "utf8",
134 'oe': "utf8",
130 'oe': "utf8",
@@ -139,18 +135,14 @@ def request(query, params):
139 if params['safesearch']:
135 if params['safesearch']:
140 query_url += '&' + urlencode({'safe': filter_mapping[params['safesearch']]})
136 query_url += '&' + urlencode({'safe': filter_mapping[params['safesearch']]})
142− params['url'] = query_url
143 logger.debug("query_url --> %s", query_url)
138 logger.debug("query_url --> %s", query_url)
139+ params['url'] = query_url
145− # en-US,en;q=0.8,en;q=0.5
141+ logger.debug("HTTP header Accept-Language --> %s", lang_info['Accept-Language'])
146− params['headers']['Accept-Language'] = (
147− "%s,%s;q=0.8,%s;q=0.5" % (lang_country, language, language))
149− "HTTP Accept-Language --> %s", params['headers']['Accept-Language'])
142+ params['headers']['Accept-Language'] = lang_info['Accept-Language']
150 params['headers']['Accept'] = (
143 params['headers']['Accept'] = (
151 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
144 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
153− #params['google_subdomain'] = subdomain
154 return params
146 return params
@@ -158,16 +150,7 @@ def response(resp):
158 """Get response from google's search request"""
150 """Get response from google's search request"""
159 results = []
151 results = []
161− # detect google sorry
153+ detect_google_sorry(resp)
162− resp_url = urlparse(resp.url)
163− if resp_url.netloc == 'sorry.google.com' or resp_url.path == '/sorry/IndexRedirect':
164− raise SearxEngineCaptchaException()
166− if resp_url.path.startswith('/sorry'):
167− raise SearxEngineCaptchaException()
170− # subdomain = resp.search_params.get('google_subdomain')
172 # convert the text to dom
155 # convert the text to dom
173 dom = html.fromstring(resp.text)
156 dom = html.fromstring(resp.text)
@@ -181,19 +164,18 @@ def response(resp):
181 logger.debug("ingoring <g-section-with-header>")
164 logger.debug("ingoring <g-section-with-header>")
184− title = extract_text(eval_xpath(result, title_xpath)[0])
167+ title = extract_text(eval_xpath_getindex(result, title_xpath, 0))
185− url = eval_xpath(result, href_xpath)[0]
168+ url = eval_xpath_getindex(result, href_xpath, 0)
186− c_node = eval_xpath(result, content_xpath)[0]
169+ c_node = eval_xpath_getindex(result, content_xpath, 0)
188 # <img id="vidthumb1" ...>
171 # <img id="vidthumb1" ...>
189− img_id = eval_xpath(c_node, './div[1]//a/g-img/img/@id')
172+ img_id = eval_xpath_getindex(c_node, './div[1]//a/g-img/img/@id', 0, default=None)
190− if not img_id:
173+ if img_id is None:
193 img_src = vidthumb_imgdata.get(img_id, None)
175 img_src = vidthumb_imgdata.get(img_id, None)
194 if not img_src:
176 if not img_src:
195 logger.error("no vidthumb imgdata for: %s" % img_id)
177 logger.error("no vidthumb imgdata for: %s" % img_id)
196− img_src = eval_xpath(c_node, './div[1]//a/g-img/img/@src')[0]
178+ img_src = eval_xpath_getindex(c_node, './div[1]//a/g-img/img/@src', 0)
198 length = extract_text(eval_xpath(c_node, './/div[1]//a/div[3]'))
180 length = extract_text(eval_xpath(c_node, './/div[1]//a/div[3]'))
199 content = extract_text(eval_xpath(c_node, './/div[2]/span'))
181 content = extract_text(eval_xpath(c_node, './/div[2]/span'))
@@ -210,11 +192,11 @@ def response(resp):
212 # parse suggestion
194 # parse suggestion
213− for suggestion in eval_xpath(dom, suggestion_xpath):
195+ for suggestion in eval_xpath_list(dom, suggestion_xpath):
214 # append suggestion
196 # append suggestion
215 results.append({'suggestion': extract_text(suggestion)})
197 results.append({'suggestion': extract_text(suggestion)})
217− for correction in eval_xpath(dom, spelling_suggestion_xpath):
199+ for correction in eval_xpath_list(dom, spelling_suggestion_xpath):
218 results.append({'correction': extract_text(correction)})
200 results.append({'correction': extract_text(correction)})
220 return results
202 return results