summaryrefslogtreecommitdiff
path: root/searx/engines/duckduckgo.py
diff options
context:
space:
mode:
authorMarkus Heiser <markus.heiser@darmarit.de>2023-09-22 08:53:19 +0200
committerMarkus Heiser <markus.heiser@darmarIT.de>2023-09-22 09:31:25 +0200
commit71358e9c673247e16125dc32b70f2553c469d814 (patch)
tree2920b593169557ce0326b0d335ef1741f403679d /searx/engines/duckduckgo.py
parent51236ae47ae24f489f85d63db90302c2d75b8129 (diff)
downloadsearxng-71358e9c673247e16125dc32b70f2553c469d814.tar.gz
searxng-71358e9c673247e16125dc32b70f2553c469d814.zip
Revert "[fix] engine - duckduckgo vqd edge-case"
This reverts commit 102502a4f09e78682cd4f030605be394bc33282c.
Diffstat (limited to 'searx/engines/duckduckgo.py')
-rw-r--r--searx/engines/duckduckgo.py67
1 files changed, 27 insertions, 40 deletions
diff --git a/searx/engines/duckduckgo.py b/searx/engines/duckduckgo.py
index d6dc3b0cc..ebb4745b9 100644
--- a/searx/engines/duckduckgo.py
+++ b/searx/engines/duckduckgo.py
@@ -57,13 +57,13 @@ url = 'https://lite.duckduckgo.com/lite/'
# url_ping = 'https://duckduckgo.com/t/sl_l'
time_range_dict = {'day': 'd', 'week': 'w', 'month': 'm', 'year': 'y'}
+form_data = {'v': 'l', 'api': 'd.js', 'o': 'json'}
def cache_vqd(query, value):
- """Caches a ``vqd`` token from a query, if token is None the cached value
- is deleted.
+ """Caches a ``vqd`` value from a query.
- The vqd token depends on the query string and is needed for the follow up
+ The vqd value depends on the query string and is needed for the follow up
pages or the images loaded by a XMLHttpRequest:
- DuckDuckGo Web: `https://links.duckduckgo.com/d.js?q=...&vqd=...`
@@ -72,27 +72,18 @@ def cache_vqd(query, value):
"""
c = redisdb.client()
if c:
+ logger.debug("cache vqd value: %s", value)
key = 'SearXNG_ddg_vqd' + redislib.secret_hash(query)
- if value is not None:
- logger.debug("cache vqd value: %s", value)
- c.set(key, value, ex=600)
- else:
- # remove from cache
- c.delete(key)
-
-
-def _get_vqd_value(query):
- res = get('https://lite.duckduckgo.com/lite/?' + urlencode({'q': query}))
- doc = lxml.html.fromstring(res.text)
- return eval_xpath_getindex(doc, "//input[@name='vqd']/@value", 0, None)
+ c.set(key, value, ex=600)
def get_vqd(query):
"""Returns the ``vqd`` that fits to the *query*. If there is no ``vqd`` cached
- (:py:obj:`cache_vqd`) the query is sent to DDG to get a vqd token from the
+ (:py:obj:`cache_vqd`) the query is sent to DDG to get a vqd value from the
response.
"""
+ value = None
c = redisdb.client()
if c:
key = 'SearXNG_ddg_vqd' + redislib.secret_hash(query)
@@ -102,20 +93,12 @@ def get_vqd(query):
logger.debug("re-use cached vqd value: %s", value)
return value
- value = _get_vqd_value(query)
- if not value:
- # seems we got a CAPTCHA for this query string, send a dummy request to
- # release the captcha and then fetch the vqd value for the query string
- # again.
- logger.warning("vqd token will no longer work, trying to get a new one by sending another query")
- _get_vqd_value(f'{query[:3]} duckduckgo')
- value = _get_vqd_value(query)
-
- if not value:
- logger.error("was not able to fetch a valid vqd token from DDG")
- else:
- logger.debug("new vqd value: %s", value)
- cache_vqd(query, value)
+ query_url = 'https://lite.duckduckgo.com/lite/?{args}'.format(args=urlencode({'q': query}))
+ res = get(query_url)
+ doc = lxml.html.fromstring(res.text)
+ value = doc.xpath("//input[@name='vqd']/@value")[0]
+ logger.debug("new vqd value: %s", value)
+ cache_vqd(query, value)
return value
@@ -258,10 +241,10 @@ def request(query, params):
# initial page does not have additional data in the input form
if params['pageno'] > 1:
- params['data']['o'] = 'json'
- params['data']['api'] = 'd.js'
- params['data']['nextParams'] = ''
- params['data']['v'] = 'l'
+ params['data']['o'] = form_data.get('o', 'json')
+ params['data']['api'] = form_data.get('api', 'd.js')
+ params['data']['nextParams'] = form_data.get('nextParams', '')
+ params['data']['v'] = form_data.get('v', 'l')
params['data']['kl'] = eng_region
params['cookies']['kl'] = eng_region
@@ -291,19 +274,23 @@ def response(resp):
# the layout of the HTML tables is different.
result_table = result_table[1]
elif not len(result_table) >= 3:
- # no more results / if we have the vqd token in cache, it's no longer
- # valid and has to be deleted
- cache_vqd(resp.search_params['data']['q'], None)
+ # no more results
return []
else:
result_table = result_table[2]
# update form data from response
form = eval_xpath(doc, '//html/body/form/div[@class="filters"]/table//input/..')
if len(form):
- value = eval_xpath_getindex(form[0], "//input[@name='vqd']/@value", 0, None)
+
+ form = form[0]
+ form_data['v'] = eval_xpath(form, '//input[@name="v"]/@value')[0]
+ form_data['api'] = eval_xpath(form, '//input[@name="api"]/@value')[0]
+ form_data['o'] = eval_xpath(form, '//input[@name="o"]/@value')[0]
+ logger.debug('form_data: %s', form_data)
+
+ value = eval_xpath(form, '//input[@name="vqd"]/@value')[0]
query = resp.search_params['data']['q']
- if value:
- cache_vqd(query, value)
+ cache_vqd(query, value)
tr_rows = eval_xpath(result_table, './/tr')
# In the last <tr> is the form of the 'previous/next page' links