[refactor] engines: migrate to SXNG_Response.html() (#6718)

This commit is contained in:
Bnyro
2026-09-13 14:01:58 +02:00
parent 3169aafd28
commit 274b63b677
75 changed files with 102 additions and 178 deletions

View File

@@ -3,7 +3,6 @@
"""1337x""" """1337x"""
from urllib.parse import quote, urljoin from urllib.parse import quote, urljoin
from lxml import html
from searx.utils import extract_text, eval_xpath, eval_xpath_list, eval_xpath_getindex from searx.utils import extract_text, eval_xpath, eval_xpath_list, eval_xpath_getindex
# about # about
@@ -31,7 +30,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, '//table[contains(@class, "table-list")]/tbody//tr'): for result in eval_xpath_list(dom, '//table[contains(@class, "table-list")]/tbody//tr'):
href = urljoin(url, eval_xpath_getindex(result, './td[contains(@class, "name")]/a[2]/@href', 0)) href = urljoin(url, eval_xpath_getindex(result, './td[contains(@class, "name")]/a[2]/@href', 0))

View File

@@ -5,7 +5,6 @@
import typing as t import typing as t
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx import logger from searx import logger
from searx.enginelib import EngineCache from searx.enginelib import EngineCache
@@ -88,7 +87,7 @@ def response(resp):
if not resp.text or not resp.text.strip(): if not resp.text or not resp.text.strip():
return [] return []
dom = html.fromstring(resp.text) dom = resp.html()
results = [] results = []
for item in dom.xpath('//li[contains(@class, "res-list")]'): for item in dom.xpath('//li[contains(@class, "res-list")]'):

View File

@@ -12,7 +12,6 @@ servers and for Docker images.
import re import re
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from dateutil import parser from dateutil import parser
from searx.utils import eval_xpath, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_list, extract_text
@@ -57,7 +56,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
doc = html.fromstring(resp.text) doc = resp.html()
for result in eval_xpath_list(doc, "//table/tbody/tr"): for result in eval_xpath_list(doc, "//table/tbody/tr"):
if len(result.xpath("./td")) < 9: if len(result.xpath("./td")) < 9:

View File

@@ -39,7 +39,6 @@ import random
import typing as t import typing as t
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from lxml.etree import ElementBase from lxml.etree import ElementBase
from searx.data import ENGINE_TRAITS from searx.data import ENGINE_TRAITS
@@ -143,7 +142,7 @@ def request(query: str, params: "OnlineParams") -> None:
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
res = EngineResults() res = EngineResults()
dom = html.fromstring(resp.text) dom = resp.html()
# Each result is a div with class "flex" inside "js-aarecord-list-outer" # Each result is a div with class "flex" inside "js-aarecord-list-outer"
# container. The "flex" filter excludes non-result div such as section # container. The "flex" filter excludes non-result div such as section
@@ -255,7 +254,7 @@ def fetch_traits(engine_traits: EngineTraits) -> None:
if not resp.ok: if not resp.ok:
raise RuntimeError("Response from Anna's Archive is not OK.") raise RuntimeError("Response from Anna's Archive is not OK.")
dom = html.fromstring(resp.text) dom = resp.html()
# supported language codes # supported language codes
lang_map: dict[str, str] = {} lang_map: dict[str, str] = {}

View File

@@ -14,7 +14,6 @@ list in ``settings.yml``:
""" """
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.result_types import EngineResults, MainResult from searx.result_types import EngineResults, MainResult
from searx.utils import eval_xpath, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_list, extract_text
@@ -62,7 +61,7 @@ def request(query, params):
def response(resp) -> EngineResults: def response(resp) -> EngineResults:
res = EngineResults() res = EngineResults()
doc = html.fromstring(resp.text) doc = resp.html()
for result in eval_xpath_list(doc, "//div[@class='article']"): for result in eval_xpath_list(doc, "//div[@class='article']"):

View File

@@ -4,7 +4,6 @@
# pylint: disable=invalid-name # pylint: disable=invalid-name
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import ( from searx.utils import (
eval_xpath_list, eval_xpath_list,
@@ -43,7 +42,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
# parse results # parse results
for result in eval_xpath_list(dom, "//div[@id='content']//div[@class='listWidget']/div/div[@class='appRow']"): for result in eval_xpath_list(dom, "//div[@id='content']//div[@class='listWidget']/div/div[@class='appRow']"):

View File

@@ -11,7 +11,6 @@ Arch Wiki blocks access to it.
from urllib.parse import urlencode, urljoin, urlparse from urllib.parse import urlencode, urljoin, urlparse
import babel import babel
import lxml
from searx.enginelib.traits import EngineTraits from searx.enginelib.traits import EngineTraits
from searx.locales import language_tag from searx.locales import language_tag
@@ -70,7 +69,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = lxml.html.fromstring(resp.text) # type: ignore dom = resp.html() # type: ignore
# get the base URL for the language in which request was made # get the base URL for the language in which request was made
sxng_lang = resp.search_params["searxng_locale"].split("-")[0] sxng_lang = resp.search_params["searxng_locale"].split("-")[0]
@@ -131,7 +130,7 @@ def fetch_traits(engine_traits: EngineTraits):
if not resp.ok: if not resp.ok:
raise RuntimeError("Response from Arch Linux Wiki is not OK.") raise RuntimeError("Response from Arch Linux Wiki is not OK.")
dom = lxml.html.fromstring(resp.text) # type: ignore dom = resp.html() # type: ignore
for a in eval_xpath_list(dom, "//a[@class='interlanguage-link-target']"): for a in eval_xpath_list(dom, "//a[@class='interlanguage-link-target']"):
sxng_tag = language_tag(babel.Locale.parse(a.get("lang"), sep="-")) sxng_tag = language_tag(babel.Locale.parse(a.get("lang"), sep="-"))
# zh_Hans --> zh # zh_Hans --> zh

View File

@@ -10,7 +10,6 @@
from urllib.parse import urlencode, urlparse, parse_qs from urllib.parse import urlencode, urlparse, parse_qs
from dateutil.parser import parse as dateparse from dateutil.parser import parse as dateparse
from lxml import html
from searx.utils import ( from searx.utils import (
eval_xpath_getindex, eval_xpath_getindex,
@@ -46,7 +45,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, '//li[contains(@class, "searchresult")]'): for result in eval_xpath_list(dom, '//li[contains(@class, "searchresult")]'):

View File

@@ -18,7 +18,6 @@ from urllib.parse import parse_qs, urlencode, urlparse
import babel import babel
import babel.languages import babel.languages
from lxml import html
from searx.enginelib.traits import EngineTraits from searx.enginelib.traits import EngineTraits
from searx.locales import region_tag from searx.locales import region_tag
@@ -96,7 +95,7 @@ def response(resp: "SXNG_Response") -> list[dict[str, t.Any]]:
results: list[dict[str, t.Any]] = [] results: list[dict[str, t.Any]] = []
dom = html.fromstring(resp.text) dom = resp.html()
for item in eval_xpath_list(dom, '//ol[@id="b_results"]/li[contains(@class, "b_algo")]'): for item in eval_xpath_list(dom, '//ol[@id="b_results"]/li[contains(@class, "b_algo")]'):
link = eval_xpath_getindex(item, ".//h2/a", 0, None) link = eval_xpath_getindex(item, ".//h2/a", 0, None)
@@ -156,7 +155,7 @@ def fetch_traits(engine_traits: EngineTraits) -> None:
if not resp.ok: if not resp.ok:
raise RuntimeError("Response from Bing is not OK.") raise RuntimeError("Response from Bing is not OK.")
dom = html.fromstring(resp.text) dom = resp.html()
map_market_codes: dict[str, str] = { map_market_codes: dict[str, str] = {
"zh-hk": "en-hk", # not sure why, but at Microslop this is the market code for Hongkong "zh-hk": "en-hk", # not sure why, but at Microslop this is the market code for Hongkong

View File

@@ -5,8 +5,6 @@ import typing as t
import json import json
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.engines.bing import fetch_traits # pylint: disable=unused-import from searx.engines.bing import fetch_traits # pylint: disable=unused-import
from searx.result_types import EngineResults from searx.result_types import EngineResults
@@ -75,7 +73,7 @@ def response(resp: "SXNG_Response") -> EngineResults:
res = EngineResults() res = EngineResults()
dom = html.fromstring(resp.text) dom = resp.html()
for result in dom.xpath('//ul[contains(@class, "dgControl_list")]/li'): for result in dom.xpath('//ul[contains(@class, "dgControl_list")]/li'):
metadata = result.xpath('.//a[@class="iusc"]/@m') metadata = result.xpath('.//a[@class="iusc"]/@m')

View File

@@ -9,8 +9,6 @@
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.enginelib.traits import EngineTraits from searx.enginelib.traits import EngineTraits
from searx.engines.bing import get_locale_params from searx.engines.bing import get_locale_params
from searx.utils import eval_xpath, eval_xpath_getindex, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_getindex, eval_xpath_list, extract_text
@@ -78,7 +76,7 @@ def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for newsitem in eval_xpath_list(dom, '//div[contains(@class, "newsitem")]'): for newsitem in eval_xpath_list(dom, '//div[contains(@class, "newsitem")]'):
link = eval_xpath_getindex(newsitem, './/a[@class="title"]', 0, None) link = eval_xpath_getindex(newsitem, './/a[@class="title"]', 0, None)

View File

@@ -4,8 +4,6 @@
import json import json
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.engines.bing import ( # pylint: disable=unused-import from searx.engines.bing import ( # pylint: disable=unused-import
fetch_traits, fetch_traits,
get_locale_params, get_locale_params,
@@ -68,7 +66,7 @@ def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for result in dom.xpath('//div[contains(@id, "mc_vtvc_video")]'): for result in dom.xpath('//div[contains(@id, "mc_vtvc_video")]'):
metadata = json.loads(eval_xpath_getindex(result, './/div[@class="vrhdata"]/@vrhm', index=0)) metadata = json.loads(eval_xpath_getindex(result, './/div[@class="vrhdata"]/@vrhm', index=0))

View File

@@ -125,7 +125,6 @@ from urllib.parse import (
) )
from dateutil import parser from dateutil import parser
from lxml import html
from searx import locales from searx import locales
from searx.enginelib.traits import EngineTraits from searx.enginelib.traits import EngineTraits
@@ -289,7 +288,7 @@ def response(resp: SXNG_Response) -> EngineResults:
def _parse_search(resp: SXNG_Response) -> EngineResults: def _parse_search(resp: SXNG_Response) -> EngineResults:
res = EngineResults() res = EngineResults()
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, "//div[contains(@class, 'snippet ')]"): for result in eval_xpath_list(dom, "//div[contains(@class, 'snippet ')]"):
url: str | None = eval_xpath_getindex(result, ".//a/@href", 0, default=None) url: str | None = eval_xpath_getindex(result, ".//a/@href", 0, default=None)
@@ -352,7 +351,7 @@ def _parse_search(resp: SXNG_Response) -> EngineResults:
def _parse_news(resp: SXNG_Response) -> EngineResults: def _parse_news(resp: SXNG_Response) -> EngineResults:
res = EngineResults() res = EngineResults()
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, "//div[@data-type='news']"): for result in eval_xpath_list(dom, "//div[@data-type='news']"):
url = eval_xpath_getindex(result, ".//a/@href", 0, default=None) url = eval_xpath_getindex(result, ".//a/@href", 0, default=None)
@@ -434,7 +433,7 @@ def fetch_traits(engine_traits: EngineTraits):
if not resp.ok: if not resp.ok:
raise RuntimeError("Response from Brave languages is not OK.") raise RuntimeError("Response from Brave languages is not OK.")
dom = html.fromstring(resp.text) dom = resp.html()
for option in dom.xpath("//section//option[@value='en-us']/../option"): for option in dom.xpath("//section//option[@value='en-us']/../option"):
ui_lang = option.get("value") ui_lang = option.get("value")

View File

@@ -38,7 +38,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
search_res = dom.xpath('//div[@class="one_result"]') search_res = dom.xpath('//div[@class="one_result"]')

View File

@@ -2,7 +2,6 @@
"""DeStatis""" """DeStatis"""
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import eval_xpath, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_list, extract_text
about = { about = {
@@ -42,7 +41,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
# filter out suggested results on further page because they're the same on each page # filter out suggested results on further page because they're the same on each page
extra_xpath = results_xpath_filter_recommended if resp.search_params['pageno'] > 1 else '' extra_xpath = results_xpath_filter_recommended if resp.search_params['pageno'] > 1 else ''

View File

@@ -4,7 +4,6 @@
import typing as t import typing as t
import urllib.parse import urllib.parse
from lxml import html
from searx.result_types import EngineResults from searx.result_types import EngineResults
from searx.utils import extract_text, eval_xpath, eval_xpath_list from searx.utils import extract_text, eval_xpath, eval_xpath_list
@@ -52,7 +51,7 @@ def request(query: str, params: "OnlineParams"):
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
res = EngineResults() res = EngineResults()
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, results_xpath): for result in eval_xpath_list(dom, results_xpath):
thumbnail_src = extract_text(eval_xpath(result, thumbnail_src_xpath)) thumbnail_src = extract_text(eval_xpath(result, thumbnail_src_xpath))

View File

@@ -4,7 +4,6 @@ Dictzone
""" """
import urllib.parse import urllib.parse
from lxml import html
from searx.utils import eval_xpath, extract_text from searx.utils import eval_xpath, extract_text
from searx.result_types import EngineResults from searx.result_types import EngineResults
@@ -50,7 +49,7 @@ def response(resp) -> EngineResults:
if not resp.ok: if not resp.ok:
return results return results
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath(dom, ".//table[@id='r']//tr"): for result in eval_xpath(dom, ".//table[@id='r']//tr"):

View File

@@ -4,7 +4,6 @@ DigBT (Videos, Music, Files)
""" """
from urllib.parse import urljoin from urllib.parse import urljoin
from lxml import html
from searx.utils import extract_text from searx.utils import extract_text
# about # about
@@ -33,7 +32,7 @@ def request(query, params):
def response(resp): def response(resp):
dom = html.fromstring(resp.text) dom = resp.html()
search_res = dom.xpath('.//td[@class="x-item"]') search_res = dom.xpath('.//td[@class="x-item"]')
if not search_res: if not search_res:

View File

@@ -172,7 +172,6 @@ import re
import typing as t import typing as t
import babel import babel
import lxml.html
from searx import locales from searx import locales
from searx.enginelib import EngineCache from searx.enginelib import EngineCache
@@ -470,7 +469,7 @@ def response(resp: "SXNG_Response") -> EngineResults:
if resp.status_code == 303: if resp.status_code == 303:
return res return res
doc = lxml.html.fromstring(resp.text) doc = resp.html()
params = resp.search_params params = resp.search_params
if is_ddg_captcha(doc): if is_ddg_captcha(doc):

View File

@@ -17,7 +17,6 @@ import typing as t
import re import re
from urllib.parse import quote_plus, urljoin from urllib.parse import quote_plus, urljoin
from lxml import html
from searx.utils import html_to_text, extract_text, eval_xpath from searx.utils import html_to_text, extract_text, eval_xpath
from searx.result_types import EngineResults from searx.result_types import EngineResults
@@ -81,7 +80,7 @@ def _fetch_first_page_link(
if resp.status_code != 200: if resp.status_code != 200:
logger.error("vqd: got HTTP %s from duckduckgo.com", resp.status_code) logger.error("vqd: got HTTP %s from duckduckgo.com", resp.status_code)
dom = html.fromstring(resp.text) dom = resp.html()
first_page_link = extract_text(eval_xpath(dom, "//link[@id='deep_preload_link']/@href")) first_page_link = extract_text(eval_xpath(dom, "//link[@id='deep_preload_link']/@href"))
if not first_page_link: if not first_page_link:

View File

@@ -2,7 +2,6 @@
"""Duden""" """Duden"""
from urllib.parse import quote, urljoin from urllib.parse import quote, urljoin
from lxml import html
from searx.utils import extract_text, eval_xpath, eval_xpath_list, eval_xpath_getindex from searx.utils import extract_text, eval_xpath, eval_xpath_list, eval_xpath_getindex
from searx.network import raise_for_httperror from searx.network import raise_for_httperror
@@ -48,7 +47,7 @@ def response(resp):
raise_for_httperror(resp) raise_for_httperror(resp)
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, '//section[not(contains(@class, "essay"))]'): for result in eval_xpath_list(dom, '//section[not(contains(@class, "essay"))]'):
url = eval_xpath_getindex(result, './/h2/a', 0).get('href') url = eval_xpath_getindex(result, './/h2/a', 0).get('href')

View File

@@ -5,7 +5,6 @@ Ebay (Videos, Music, Files)
from urllib.parse import quote from urllib.parse import quote
from lxml import html
from searx.engines.xpath import extract_text from searx.engines.xpath import extract_text
# about # about
@@ -44,7 +43,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
results_dom = dom.xpath(results_xpath) results_dom = dom.xpath(results_xpath)
if not results_dom: if not results_dom:
return [] return []

View File

@@ -9,7 +9,6 @@ since 2021. Emojipedia is a voting member of The Unicode Consortium.[1]
""" """
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import ( from searx.utils import (
eval_xpath_list, eval_xpath_list,
@@ -41,7 +40,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, '//div[starts-with(@class, "EmojisList")]/a'): for result in eval_xpath_list(dom, '//div[starts-with(@class, "EmojisList")]/a'):

View File

@@ -4,7 +4,6 @@ F-Droid (a repository of FOSS applications for Android)
""" """
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import extract_text from searx.utils import extract_text
# about # about
@@ -37,7 +36,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for app in dom.xpath('//a[@class="package-header"]'): for app in dom.xpath('//a[@class="package-header"]'):
app_url = app.xpath('./@href')[0] app_url = app.xpath('./@href')[0]

View File

@@ -13,8 +13,6 @@ from os.path import basename
from urllib.parse import urlencode from urllib.parse import urlencode
import typing as t import typing as t
from lxml import html
from searx.result_types import EngineResults from searx.result_types import EngineResults
from searx.utils import extract_text, eval_xpath, eval_xpath_list from searx.utils import extract_text, eval_xpath, eval_xpath_list
@@ -76,7 +74,7 @@ def request(query: str, params: "OnlineParams") -> None:
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
res = EngineResults() res = EngineResults()
dom = html.fromstring(resp.text) dom = resp.html()
if findfiles_categ == "image": if findfiles_categ == "image":
for result in eval_xpath_list( for result in eval_xpath_list(
dom, "//div[contains(@class, 'image-mosaic')]/div[contains(@class, 'image-item')]" dom, "//div[contains(@class, 'image-mosaic')]/div[contains(@class, 'image-item')]"

View File

@@ -16,7 +16,6 @@ to the search term:
import re import re
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import eval_xpath, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_list, extract_text
@@ -67,7 +66,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, "//article[contains(@class, 'listview__item')]"): for result in eval_xpath_list(dom, "//article[contains(@class, 'listview__item')]"):
content = [] content = []
for spec in eval_xpath_list(result, ".//div[contains(@class, 'specs-grid__item')]"): for spec in eval_xpath_list(result, ".//div[contains(@class, 'specs-grid__item')]"):

View File

@@ -7,8 +7,6 @@ import re
import typing as t import typing as t
from lxml import html
from searx.enginelib import EngineCache from searx.enginelib import EngineCache
from searx.exceptions import SearxEngineAPIException from searx.exceptions import SearxEngineAPIException
from searx.network import get from searx.network import get
@@ -67,8 +65,7 @@ def _get_api_key() -> str:
if cached: if cached:
return cached return cached
homepage_resp = get(base_url) homepage_doc = get(base_url).html()
homepage_doc = html.fromstring(homepage_resp.text)
for script_src in eval_xpath_list(homepage_doc, "//script[contains(@src, 'layout')]/@src"): for script_src in eval_xpath_list(homepage_doc, "//script[contains(@src, 'layout')]/@src"):
script_resp = get(base_url + script_src) script_resp = get(base_url + script_src)

View File

@@ -10,7 +10,6 @@ import time
import typing as t import typing as t
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.result_types import EngineResults from searx.result_types import EngineResults
from searx.exceptions import SearxEngineCaptchaException from searx.exceptions import SearxEngineCaptchaException
@@ -43,7 +42,7 @@ def _get_page_hash(query: str, page: int, headers: dict[str, str]) -> str:
resp = get(f"{base_url}/web/result?q={query}&page={page}", headers=headers) resp = get(f"{base_url}/web/result?q={query}&page={page}", headers=headers)
# detect captcha (if any) # detect captcha (if any)
doc = html.fromstring(resp.text) doc = resp.html()
if eval_xpath(doc, "//*[@id='spam-messages']"): if eval_xpath(doc, "//*[@id='spam-messages']"):
raise SearxEngineCaptchaException() raise SearxEngineCaptchaException()

View File

@@ -3,7 +3,6 @@
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import extract_text, eval_xpath, eval_xpath_list from searx.utils import extract_text, eval_xpath, eval_xpath_list
about = { about = {
@@ -40,7 +39,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, results_xpath): for result in eval_xpath_list(dom, results_xpath):
results.append( results.append(

View File

@@ -2,7 +2,6 @@
"""Google Play Apps & Google Play Movies""" """Google Play Apps & Google Play Movies"""
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import ( from searx.utils import (
eval_xpath, eval_xpath,
extract_url, extract_url,
@@ -52,7 +51,7 @@ def response(resp):
def response_movies(resp): def response_movies(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for section in eval_xpath(dom, '//c-wiz/section/header/..'): for section in eval_xpath(dom, '//c-wiz/section/header/..'):
sec_name = extract_text(eval_xpath(section, './header')) sec_name = extract_text(eval_xpath(section, './header'))
@@ -79,7 +78,7 @@ def response_movies(resp):
def response_apps(resp): def response_apps(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
if eval_xpath(dom, '//div[@class="v6DsQb"]'): if eval_xpath(dom, '//div[@class="v6DsQb"]'):
return [] return []

View File

@@ -26,7 +26,6 @@ import typing as t
from urllib.parse import urlencode from urllib.parse import urlencode
from datetime import datetime from datetime import datetime
from lxml import html
from curl_cffi.requests.exceptions import TooManyRedirects from curl_cffi.requests.exceptions import TooManyRedirects
from searx.utils import ( from searx.utils import (
@@ -106,7 +105,7 @@ def response(resp: "SXNG_Response") -> EngineResults: # pylint: disable=too-man
raise TooManyRedirects(f"location {resp.headers['Location'].split('?')[0]}") raise TooManyRedirects(f"location {resp.headers['Location'].split('?')[0]}")
res = EngineResults() res = EngineResults()
dom = html.fromstring(resp.text) dom = resp.html()
detect_google_captcha(dom) detect_google_captcha(dom)
# parse results # parse results

View File

@@ -2,7 +2,6 @@
"""Imgur (images)""" """Imgur (images)"""
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import extract_text, eval_xpath, eval_xpath_list from searx.utils import extract_text, eval_xpath, eval_xpath_list
about = { about = {
@@ -40,7 +39,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, results_xpath): for result in eval_xpath_list(dom, results_xpath):
thumbnail_src = extract_text(eval_xpath(result, thumbnail_xpath)) thumbnail_src = extract_text(eval_xpath(result, thumbnail_xpath))

View File

@@ -5,7 +5,6 @@ INA (Videos)
from html import unescape from html import unescape
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import extract_text, eval_xpath, eval_xpath_list, eval_xpath_getindex from searx.utils import extract_text, eval_xpath, eval_xpath_list, eval_xpath_getindex
# about # about
@@ -48,7 +47,7 @@ def response(resp):
results = [] results = []
# we get html in a JSON container... # we get html in a JSON container...
dom = html.fromstring(resp.text) dom = resp.html()
# parse results # parse results
for result in eval_xpath_list(dom, results_xpath): for result in eval_xpath_list(dom, results_xpath):

View File

@@ -5,7 +5,6 @@ from datetime import datetime
from json import loads, JSONDecodeError from json import loads, JSONDecodeError
from urllib.parse import quote_plus from urllib.parse import quote_plus
from lxml import html
from searx.utils import extr, extract_text, eval_xpath, eval_xpath_list from searx.utils import extr, extract_text, eval_xpath, eval_xpath_list
@@ -33,7 +32,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
doc = html.fromstring(resp.text) doc = resp.html()
images = eval_xpath_list(doc, '//a[starts-with(@href, "/doc")]//img') images = eval_xpath_list(doc, '//a[starts-with(@href, "/doc")]//img')

View File

@@ -5,7 +5,6 @@ import random
from operator import itemgetter from operator import itemgetter
from urllib.parse import quote from urllib.parse import quote
from lxml import html
from searx.utils import ( from searx.utils import (
eval_xpath, eval_xpath,
eval_xpath_getindex, eval_xpath_getindex,
@@ -39,7 +38,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
search_res = eval_xpath_list(dom, '//table[contains(@class, "data")]//tr[descendant::a]', None) search_res = eval_xpath_list(dom, '//table[contains(@class, "data")]//tr[descendant::a]', None)
if search_res is None: if search_res is None:

View File

@@ -2,7 +2,6 @@
"""lib.rs (packages)""" """lib.rs (packages)"""
from urllib.parse import quote_plus from urllib.parse import quote_plus
from lxml import html
from searx.utils import eval_xpath, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_list, extract_text
about = { about = {
@@ -35,7 +34,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
doc = html.fromstring(resp.text) doc = resp.html()
for result in eval_xpath_list(doc, results_xpath): for result in eval_xpath_list(doc, results_xpath):
package_name = extract_text(eval_xpath(result, title_xpath)) package_name = extract_text(eval_xpath(result, title_xpath))

View File

@@ -9,7 +9,6 @@ from json import dumps
from urllib.parse import quote_plus, unquote_plus from urllib.parse import quote_plus, unquote_plus
import typing as t import typing as t
from lxml import html
from searx.result_types import EngineResults from searx.result_types import EngineResults
from searx.network import get from searx.network import get
@@ -188,7 +187,7 @@ def _image_results(doc: ElementType, res: EngineResults):
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
doc = html.fromstring(resp.text) doc = resp.html()
res = EngineResults() res = EngineResults()
match luxxle_categ: match luxxle_categ:

View File

@@ -10,7 +10,6 @@ from urllib.parse import urlencode
import curl_cffi import curl_cffi
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from lxml import html
from searx.exceptions import SearxEngineAPIException from searx.exceptions import SearxEngineAPIException
from searx.enginelib import EngineCache from searx.enginelib import EngineCache
@@ -177,7 +176,7 @@ def _news_results(dom) -> EngineResults:
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
dom = html.fromstring(resp.text) dom = resp.html()
if search_type == "": if search_type == "":
return _general_results(dom) return _general_results(dom)
@@ -207,7 +206,7 @@ def fetch_traits(engine_traits: EngineTraits):
if not resp.ok: if not resp.ok:
raise RuntimeError("Response from Mojeek is not OK.") raise RuntimeError("Response from Mojeek is not OK.")
dom = html.fromstring(resp.text) dom = resp.html()
languages = eval_xpath_list(dom, f'//select[@name="{language_param}"]/option/@value') languages = eval_xpath_list(dom, f'//select[@name="{language_param}"]/option/@value')

View File

@@ -7,8 +7,6 @@
from urllib.parse import urlencode from urllib.parse import urlencode
import typing as t import typing as t
from lxml import html
from searx.utils import eval_xpath, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_list, extract_text
from searx.result_types import EngineResults from searx.result_types import EngineResults
@@ -51,7 +49,7 @@ def request(query: str, params: "OnlineParams") -> None:
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
results = EngineResults() results = EngineResults()
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, results_xpath): for result in eval_xpath_list(dom, results_xpath):
results.add( results.add(

View File

@@ -7,8 +7,6 @@
from json import loads from json import loads
import typing as t import typing as t
from lxml import html
from searx.exceptions import SearxEngineAPIException from searx.exceptions import SearxEngineAPIException
from searx.extended_types import SXNG_Response from searx.extended_types import SXNG_Response
from searx.network import get from searx.network import get
@@ -38,7 +36,7 @@ categories = ["general"]
def _obtain_xsrf_token() -> str: def _obtain_xsrf_token() -> str:
resp = get(base_url) resp = get(base_url)
doc = html.fromstring(resp.text) doc = resp.html()
xsrf_token = extract_text(eval_xpath(doc, "//meta[@name='xsrf-token']/@content")) xsrf_token = extract_text(eval_xpath(doc, "//meta[@name='xsrf-token']/@content"))
if not xsrf_token: if not xsrf_token:

View File

@@ -3,7 +3,6 @@
from urllib.parse import urlencode from urllib.parse import urlencode
from datetime import datetime, timedelta from datetime import datetime, timedelta
from lxml import html
from searx.utils import eval_xpath_getindex, eval_xpath_list, eval_xpath, extract_text from searx.utils import eval_xpath_getindex, eval_xpath_list, eval_xpath, extract_text
@@ -48,7 +47,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for item in eval_xpath_list(dom, results_xpath): for item in eval_xpath_list(dom, results_xpath):
relative_url = eval_xpath_getindex(item, url_xpath, 0) relative_url = eval_xpath_getindex(item, url_xpath, 0)

View File

@@ -3,7 +3,6 @@
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import ( from searx.utils import (
eval_xpath_getindex, eval_xpath_getindex,
extract_text, extract_text,
@@ -55,7 +54,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for result in dom.xpath(xpath_results): for result in dom.xpath(xpath_results):
# defaults # defaults

View File

@@ -3,7 +3,6 @@
from urllib.parse import urlencode from urllib.parse import urlencode
from datetime import datetime from datetime import datetime
from lxml import html
from searx.utils import eval_xpath_list, eval_xpath_getindex, eval_xpath, extract_text from searx.utils import eval_xpath_list, eval_xpath_getindex, eval_xpath, extract_text
from searx.result_types import EngineResults from searx.result_types import EngineResults
@@ -37,7 +36,7 @@ def request(query, params):
def response(resp) -> EngineResults: def response(resp) -> EngineResults:
res = EngineResults() res = EngineResults()
dom = html.fromstring(resp.text) dom = resp.html()
for item in eval_xpath_list(dom, results_xpath): for item in eval_xpath_list(dom, results_xpath):
published_date = None published_date = None

View File

@@ -2,7 +2,6 @@
"""OpenClipArt (images)""" """OpenClipArt (images)"""
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import extract_text, eval_xpath, eval_xpath_list from searx.utils import extract_text, eval_xpath, eval_xpath_list
about = { about = {
@@ -32,7 +31,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, "//div[contains(@class, 'gallery')]/div[contains(@class, 'artwork')]"): for result in eval_xpath_list(dom, "//div[contains(@class, 'gallery')]/div[contains(@class, 'artwork')]"):
results.append( results.append(

View File

@@ -5,7 +5,6 @@ import re
import typing as t import typing as t
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.result_types import EngineResults from searx.result_types import EngineResults
from searx.utils import eval_xpath_list from searx.utils import eval_xpath_list
@@ -62,7 +61,7 @@ def _get_secret_key():
if resp.status_code != 200: if resp.status_code != 200:
raise SearxEngineAPIException("failed to obtain secret key") raise SearxEngineAPIException("failed to obtain secret key")
doc = html.fromstring(resp.text) doc = resp.html()
for script_src in eval_xpath_list(doc, "//script/@src"): for script_src in eval_xpath_list(doc, "//script/@src"):
script = get(script_src) script = get(script_src)
if script.status_code != 200: if script.status_code != 200:

View File

@@ -7,8 +7,6 @@
from urllib.parse import urlparse, urlunparse from urllib.parse import urlparse, urlunparse
import typing as t import typing as t
from lxml import html
from searx.result_types import EngineResults from searx.result_types import EngineResults
from searx.utils import eval_xpath, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_list, extract_text
@@ -46,7 +44,7 @@ def _get_max_res_url(url: str) -> str:
def response(resp: "SXNG_Response"): def response(resp: "SXNG_Response"):
res = EngineResults() res = EngineResults()
doc = html.fromstring(resp.text) doc = resp.html()
for result in eval_xpath_list(doc, "//div[contains(@class, 'photo_query')]/div[contains(@class, 'photo_item')]"): for result in eval_xpath_list(doc, "//div[contains(@class, 'photo_query')]/div[contains(@class, 'photo_item')]"):
thumbnail = extract_text(eval_xpath(result, ".//img[contains(@class, 'image')]/@src")) or "" thumbnail = extract_text(eval_xpath(result, ".//img[contains(@class, 'image')]/@src")) or ""

View File

@@ -7,7 +7,6 @@ from dateutil import parser
import babel import babel
import flask_babel import flask_babel
from lxml import html
from searx.utils import eval_xpath, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_list, extract_text
about = { about = {
@@ -51,7 +50,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
doc = html.fromstring(resp.text) doc = resp.html()
for result in eval_xpath_list(doc, results_xpath): for result in eval_xpath_list(doc, results_xpath):
publishedDate = extract_text(eval_xpath(result, updated_xpath)) publishedDate = extract_text(eval_xpath(result, updated_xpath))

View File

@@ -10,7 +10,6 @@ user information with Microsoft and Amazon.
import typing as t import typing as t
from urllib.parse import urlencode, unquote_plus from urllib.parse import urlencode, unquote_plus
from lxml import html
import babel import babel
from searx.enginelib.traits import EngineTraits from searx.enginelib.traits import EngineTraits
@@ -160,7 +159,7 @@ def _video_results(doc: "ElementBase") -> EngineResults:
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
doc = html.fromstring(resp.text) doc = resp.html()
match privacywall_category: match privacywall_category:
case "general": case "general":
return _general_results(doc) return _general_results(doc)
@@ -187,7 +186,7 @@ def fetch_traits(engine_traits: EngineTraits) -> None:
if not resp.ok: if not resp.ok:
raise RuntimeError("Response from Privacywall is not OK.") raise RuntimeError("Response from Privacywall is not OK.")
dom = html.fromstring(resp.text) dom = resp.html()
# <div class="dropdown-option" onclick="changeMenuLanguage(&quot;CZ&quot;)"></div> # <div class="dropdown-option" onclick="changeMenuLanguage(&quot;CZ&quot;)"></div>
for onclick_listener in eval_xpath( for onclick_listener in eval_xpath(

View File

@@ -4,7 +4,6 @@
from urllib.parse import urlencode from urllib.parse import urlencode
from dateutil import parser from dateutil import parser
from lxml import html
from searx.utils import ( from searx.utils import (
eval_xpath_getindex, eval_xpath_getindex,
eval_xpath_list, eval_xpath_list,
@@ -41,7 +40,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for entry in eval_xpath_list(dom, '/html/body/main/div/div/div/form/div/ul/li/a[@class="package-snippet"]'): for entry in eval_xpath_list(dom, '/html/body/main/div/div/div/form/div/ul/li/a[@class="package-snippet"]'):
url = base_url + extract_text(eval_xpath_getindex(entry, './@href', 0)) # type: ignore url = base_url + extract_text(eval_xpath_getindex(entry, './@href', 0)) # type: ignore
title = extract_text(eval_xpath_getindex(entry, './h3/span[@class="package-snippet__name"]', 0)) title = extract_text(eval_xpath_getindex(entry, './h3/span[@class="package-snippet__name"]', 0))

View File

@@ -7,8 +7,6 @@
import typing as t import typing as t
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx import locales from searx import locales
from searx.exceptions import SearxEngineResponseException from searx.exceptions import SearxEngineResponseException
from searx.result_types import EngineResults from searx.result_types import EngineResults
@@ -111,7 +109,7 @@ def _image_results(doc: "ElementBase") -> EngineResults:
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
doc = html.fromstring(resp.text) doc = resp.html()
# if the request was wrong (e.g. missing params), the site doesn't contain a result container # if the request was wrong (e.g. missing params), the site doesn't contain a result container
# and instead shows an "Installation required" page to download the resulthunter browser extension # and instead shows an "Installation required" page to download the resulthunter browser extension

View File

@@ -2,7 +2,6 @@
"""RottenTomatoes (movies)""" """RottenTomatoes (movies)"""
from urllib.parse import quote_plus from urllib.parse import quote_plus
from lxml import html
from searx.utils import eval_xpath, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_list, extract_text
# about # about
@@ -35,7 +34,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, results_xpath): for result in eval_xpath_list(dom, results_xpath):
content = [] content = []

View File

@@ -4,7 +4,6 @@
from datetime import datetime from datetime import datetime
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
# about # about
from searx.utils import extract_text from searx.utils import extract_text
@@ -46,7 +45,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
results_dom = dom.xpath('//li[contains(@class, "video-listing-entry")]') results_dom = dom.xpath('//li[contains(@class, "video-listing-entry")]')
if not results_dom: if not results_dom:

View File

@@ -11,8 +11,6 @@ Some of the engines get their results from Google, others get them from Yahoo.
import typing as t import typing as t
from urllib.parse import urlencode, urlparse, parse_qs from urllib.parse import urlencode, urlparse, parse_qs
from lxml import html
from searx.result_types import EngineResults from searx.result_types import EngineResults
from searx.enginelib import EngineCache from searx.enginelib import EngineCache
from searx.utils import eval_xpath_list, eval_xpath, extract_text from searx.utils import eval_xpath_list, eval_xpath, extract_text
@@ -68,7 +66,7 @@ def request(query: str, params: "OnlineParams"):
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
res = EngineResults() res = EngineResults()
doc = html.fromstring(resp.text) doc = resp.html()
for suggestion in eval_xpath_list(doc, "//div[@class='aylf-yahoo-bottom' or @class='aylf-yahoo-sidebar']/div"): for suggestion in eval_xpath_list(doc, "//div[@class='aylf-yahoo-bottom' or @class='aylf-yahoo-sidebar']/div"):
res.add(res.types.LegacyResult({"suggestion": extract_text(suggestion)})) res.add(res.types.LegacyResult({"suggestion": extract_text(suggestion)}))

View File

@@ -4,7 +4,6 @@ but the results seem to come from Google."""
import typing as t import typing as t
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from dateutil import parser from dateutil import parser
from searx.result_types import EngineResults from searx.result_types import EngineResults
@@ -46,7 +45,7 @@ def request(query: str, params: "OnlineParams") -> None:
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
doc = html.fromstring(resp.text) doc = resp.html()
res = EngineResults() res = EngineResults()
match searchrockit_categ: match searchrockit_categ:

View File

@@ -26,7 +26,6 @@ Implementations
import typing as t import typing as t
from datetime import datetime from datetime import datetime
from lxml import html
from flask_babel import gettext # pyright: ignore[reportUnknownVariableType] from flask_babel import gettext # pyright: ignore[reportUnknownVariableType]
from searx.network import get from searx.network import get
@@ -70,7 +69,7 @@ def get_ui_version() -> str:
if not resp.ok: if not resp.ok:
raise RuntimeError("Can't determine Semantic Scholar UI version") raise RuntimeError("Can't determine Semantic Scholar UI version")
doc = html.fromstring(resp.text) doc = resp.html()
ret_val = eval_xpath_getindex(doc, "//meta[@name='s2-ui-version']/@content", 0) ret_val = eval_xpath_getindex(doc, "//meta[@name='s2-ui-version']/@content", 0)
if not ret_val: if not ret_val:
raise RuntimeError("Can't determine Semantic Scholar UI version") raise RuntimeError("Can't determine Semantic Scholar UI version")

View File

@@ -2,7 +2,6 @@
"""Seznam""" """Seznam"""
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.network import get from searx.network import get
from searx.exceptions import SearxEngineAccessDeniedException from searx.exceptions import SearxEngineAccessDeniedException
from searx.utils import ( from searx.utils import (
@@ -28,7 +27,7 @@ base_url = 'https://search.seznam.cz/'
def request(query, params): def request(query, params):
response_index = get(base_url, headers=params['headers'], raise_for_httperror=True, timeout=3) response_index = get(base_url, headers=params['headers'], raise_for_httperror=True, timeout=3)
dom = html.fromstring(response_index.text) dom = response_index.html()
url_params = { url_params = {
'q': query, 'q': query,
@@ -50,7 +49,7 @@ def response(resp):
results = [] results = []
dom = html.fromstring(resp.content.decode()) dom = resp.html()
for result_element in eval_xpath_list( for result_element in eval_xpath_list(
dom, '//div[@id="searchpage-root"]//div[@class="Layout--left"]/div[@class="f2c528"]' dom, '//div[@id="searchpage-root"]//div[@class="Layout--left"]/div[@class="f2c528"]'
): ):

View File

@@ -6,8 +6,6 @@ Shopify.
import typing as t import typing as t
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.result_types import EngineResults from searx.result_types import EngineResults
from searx.utils import eval_xpath, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_list, extract_text
@@ -45,7 +43,7 @@ def _get_download_url(url: str) -> str:
def response(resp: "SXNG_Response"): def response(resp: "SXNG_Response"):
res = EngineResults() res = EngineResults()
doc = html.fromstring(resp.text) doc = resp.html()
for result in eval_xpath_list(doc, "//div[contains(@class, 'js-masonry-grid')]/div"): for result in eval_xpath_list(doc, "//div[contains(@class, 'js-masonry-grid')]/div"):
url = base_url + (extract_text(eval_xpath(result, ".//a[contains(@class, 'photo-tile')]/@href")) or "") url = base_url + (extract_text(eval_xpath(result, ".//a[contains(@class, 'photo-tile')]/@href")) or "")

View File

@@ -58,7 +58,7 @@ def response(resp):
): ):
raise SearxEngineCaptchaException() raise SearxEngineCaptchaException()
dom = html.fromstring(resp.text) dom = resp.html()
results = [] results = []
# pylint: disable=line-too-long # pylint: disable=line-too-long

View File

@@ -4,7 +4,6 @@
from urllib.parse import urlencode from urllib.parse import urlencode
from datetime import datetime from datetime import datetime
import re import re
from lxml import html
from searx.utils import extract_text from searx.utils import extract_text
@@ -37,7 +36,7 @@ def request(query, params):
def response(resp): def response(resp):
dom = html.fromstring(resp.text) dom = resp.html()
results = [] results = []
for item in dom.xpath('//li[contains(@id, "sogou_vr_")]'): for item in dom.xpath('//li[contains(@id, "sogou_vr_")]'):

View File

@@ -5,8 +5,6 @@ from datetime import datetime
from urllib.parse import urlencode from urllib.parse import urlencode
import random import random
from lxml import html
from searx.utils import ( from searx.utils import (
extract_text, extract_text,
eval_xpath, eval_xpath,
@@ -43,7 +41,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath(dom, '//li[contains(@class, "search-result")]'): for result in eval_xpath(dom, '//li[contains(@class, "search-result")]'):
torrentfile = eval_xpath_getindex(result, './/a[contains(@class, "dl-torrent")]/@href', 0, None) torrentfile = eval_xpath_getindex(result, './/a[contains(@class, "dl-torrent")]/@href', 0, None)

View File

@@ -25,7 +25,6 @@ Implementations
import typing as t import typing as t
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import eval_xpath, eval_xpath_list, extract_text, searxng_useragent from searx.utils import eval_xpath, eval_xpath_list, extract_text, searxng_useragent
from searx.result_types import EngineResults from searx.result_types import EngineResults
@@ -71,7 +70,7 @@ def request(query: str, params: "OnlineParams") -> None:
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
res = EngineResults() res = EngineResults()
doc = html.fromstring(resp.text) doc = resp.html()
for item in eval_xpath_list(doc, "(//div[@class='event-list'])[1]/div[contains(@class, 'event')]"): for item in eval_xpath_list(doc, "(//div[@class='event-list'])[1]/div[contains(@class, 'event')]"):
res.add( res.add(

View File

@@ -98,7 +98,6 @@ from unicodedata import combining, normalize
import babel.localedata import babel.localedata
import dateutil.parser import dateutil.parser
import lxml.html
from searx.enginelib import EngineCache from searx.enginelib import EngineCache
from searx.enginelib.traits import EngineTraits from searx.enginelib.traits import EngineTraits
@@ -257,7 +256,7 @@ def get_sc_code(params):
message="get_sc_code: got redirected to https://www.startpage.com/sp/captcha", message="get_sc_code: got redirected to https://www.startpage.com/sp/captcha",
) )
dom = lxml.html.fromstring(resp.text) dom = resp.html()
try: try:
sc_code = eval_xpath(dom, search_form_xpath + '//input[@name="sc"]/@value')[0] sc_code = eval_xpath(dom, search_form_xpath + '//input[@name="sc"]/@value')[0]
@@ -503,7 +502,7 @@ def fetch_traits(engine_traits: EngineTraits):
if not resp.ok: if not resp.ok:
raise RuntimeError("Response from Startpage is not OK.") raise RuntimeError("Response from Startpage is not OK.")
dom = lxml.html.fromstring(resp.text) dom = resp.html()
# regions # regions

View File

@@ -11,7 +11,6 @@ from urllib.parse import urlencode
import typing as t import typing as t
from dateutil import parser from dateutil import parser
from lxml import html
from searx.exceptions import SearxEngineAPIException from searx.exceptions import SearxEngineAPIException
from searx.extended_types import SXNG_Response from searx.extended_types import SXNG_Response
@@ -72,7 +71,7 @@ def _obtain_session_code() -> str:
return cached_session return cached_session
results_page = get(f"{base_url}/checkCode.aspx") results_page = get(f"{base_url}/checkCode.aspx")
doc = html.fromstring(results_page.text) doc = results_page.html()
extra_data: dict[str, str] = {} extra_data: dict[str, str] = {}
for extra_param in ("__VIEWSTATE", "__VIEWSTATEGENERATOR", "__EVENTVALIDATION"): for extra_param in ("__VIEWSTATE", "__VIEWSTATEGENERATOR", "__EVENTVALIDATION"):
@@ -130,7 +129,7 @@ def request(query: str, params: "OnlineParams"):
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
res = EngineResults() res = EngineResults()
doc = html.fromstring(resp.text) doc = resp.html()
if tiger_category == "Websuche": if tiger_category == "Websuche":
for result in eval_xpath_list(doc, "//div[@id='mainContainer']//table/tr"): for result in eval_xpath_list(doc, "//div[@id='mainContainer']//table/tr"):

View File

@@ -5,7 +5,6 @@ import re
from datetime import datetime from datetime import datetime
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import extract_text, int_or_zero from searx.utils import extract_text, int_or_zero
# about # about
@@ -38,7 +37,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
rows = dom.xpath('//table[@class="listing"]//tr[contains(@class, "category_0")]') rows = dom.xpath('//table[@class="listing"]//tr[contains(@class, "category_0")]')
# check if there are no results or page layout was changed so we cannot parse it # check if there are no results or page layout was changed so we cannot parse it

View File

@@ -12,8 +12,6 @@ results from YouTube.
import typing as t import typing as t
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import eval_xpath_list, eval_xpath, extract_text, ElementType from searx.utils import eval_xpath_list, eval_xpath, extract_text, ElementType
from searx.result_types import EngineResults from searx.result_types import EngineResults
from searx.enginelib import EngineAbout from searx.enginelib import EngineAbout
@@ -131,7 +129,7 @@ def _video_results(doc: ElementType, res: EngineResults):
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
doc = html.fromstring(resp.text) doc = resp.html()
res = EngineResults() res = EngineResults()
match tonline_categ: match tonline_categ:
case "web": case "web":

View File

@@ -2,7 +2,6 @@
"""UXwing (images)""" """UXwing (images)"""
from urllib.parse import quote_plus from urllib.parse import quote_plus
from lxml import html
from searx.utils import eval_xpath, eval_xpath_list, extract_text from searx.utils import eval_xpath, eval_xpath_list, extract_text
@@ -26,7 +25,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
doc = html.fromstring(resp.text) doc = resp.html()
for result in eval_xpath_list(doc, "//article[starts-with(@id, 'post')]"): for result in eval_xpath_list(doc, "//article[starts-with(@id, 'post')]"):
classes = extract_text(eval_xpath(result, "./@class")).split(" ") classes = extract_text(eval_xpath(result, "./@class")).split(" ")
tags = [] tags = []

View File

@@ -7,8 +7,6 @@
import typing as t import typing as t
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.result_types import EngineResults from searx.result_types import EngineResults
from searx.utils import eval_xpath_list, eval_xpath, extract_text from searx.utils import eval_xpath_list, eval_xpath, extract_text
@@ -101,7 +99,7 @@ def _video_results(doc: "ElementBase") -> EngineResults:
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
doc = html.fromstring(resp.text) doc = resp.html()
match vuhuv_category: match vuhuv_category:
case "general": case "general":
return _general_results(doc) return _general_results(doc)

View File

@@ -57,7 +57,6 @@ options:
import urllib.parse import urllib.parse
import babel import babel
from lxml import html
from searx import locales, utils from searx import locales, utils
from searx import network as _network from searx import network as _network
@@ -285,7 +284,7 @@ def fetch_wikimedia_traits(engine_traits: EngineTraits):
if not resp.ok: if not resp.ok:
raise RuntimeError("Response from Wikipedia is not OK.") raise RuntimeError("Response from Wikipedia is not OK.")
dom = html.fromstring(resp.text) dom = resp.html()
for row in dom.xpath('//table[contains(@class,"sortable")]//tbody/tr'): for row in dom.xpath('//table[contains(@class,"sortable")]//tbody/tr'):
cols = row.xpath("./td") cols = row.xpath("./td")
if not cols: if not cols:

View File

@@ -72,7 +72,6 @@ Implementations
from urllib.parse import urlencode from urllib.parse import urlencode
from lxml import html
from searx.utils import extract_text, extract_url, eval_xpath, eval_xpath_list from searx.utils import extract_text, extract_url, eval_xpath, eval_xpath_list
from searx.network import raise_for_httperror from searx.network import raise_for_httperror
from searx.result_types import EngineResults from searx.result_types import EngineResults
@@ -287,7 +286,7 @@ def response(resp) -> EngineResults: # pylint: disable=too-many-branches
if not resp.text: if not resp.text:
return results return results
dom = html.fromstring(resp.text) dom = resp.html()
is_onion = 'onions' in categories is_onion = 'onions' in categories
if results_xpath: if results_xpath:

View File

@@ -9,8 +9,6 @@ named `YBV`, which is cached for 24h before expiring.
import typing as t import typing as t
from urllib.parse import unquote, urlencode, urljoin from urllib.parse import unquote, urlencode, urljoin
from lxml import html
from searx.enginelib import EngineCache from searx.enginelib import EngineCache
from searx.network import get # see https://github.com/searxng/searxng/issues/762 from searx.network import get # see https://github.com/searxng/searxng/issues/762
from searx.result_types import EngineResults from searx.result_types import EngineResults
@@ -184,7 +182,6 @@ def parse_url(url_string: str) -> str:
def _yahoo_html(resp: "SXNG_Response") -> "SXNG_Response": def _yahoo_html(resp: "SXNG_Response") -> "SXNG_Response":
cookies = dict(resp.search_params["cookies"]) cookies = dict(resp.search_params["cookies"])
params = resp.search_params params = resp.search_params
for _ in range(_YBV_HOPS): for _ in range(_YBV_HOPS):
if ybv := resp.cookies.get("YBV"): if ybv := resp.cookies.get("YBV"):
cookies["YBV"] = ybv cookies["YBV"] = ybv
@@ -215,7 +212,7 @@ def response(resp: "SXNG_Response") -> EngineResults:
results = EngineResults() results = EngineResults()
if resp.status_code != 200: if resp.status_code != 200:
resp.raise_for_status() resp.raise_for_status()
dom = html.fromstring(resp.text) dom = resp.html()
for result in eval_xpath_list(dom, '//div[contains(@class,"algo-sr")]'): for result in eval_xpath_list(dom, '//div[contains(@class,"algo-sr")]'):
url = eval_xpath_getindex(result, './/div[contains(@class,"compTitle")]//a/@href', 0, default=None) url = eval_xpath_getindex(result, './/div[contains(@class,"compTitle")]//a/@href', 0, default=None)

View File

@@ -11,7 +11,6 @@ import re
from urllib.parse import urlencode from urllib.parse import urlencode
from datetime import datetime, timedelta from datetime import datetime, timedelta
from dateutil import parser from dateutil import parser
from lxml import html
from searx.utils import ( from searx.utils import (
eval_xpath_list, eval_xpath_list,
@@ -66,7 +65,7 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
dom = html.fromstring(resp.text) dom = resp.html()
# parse results # parse results
for result in eval_xpath_list(dom, '//ol[contains(@class,"searchCenterMiddle")]//li'): for result in eval_xpath_list(dom, '//ol[contains(@class,"searchCenterMiddle")]//li'):

View File

@@ -135,7 +135,7 @@ def _parse_json_results(dom: html.HtmlElement) -> dict[str, t.Any]:
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
catch_bad_response(resp) catch_bad_response(resp)
results = EngineResults() results = EngineResults()
dom = html.fromstring(resp.text) dom = resp.html()
match search_type: match search_type:
case "web": case "web":

View File

@@ -80,7 +80,6 @@ def fetch_traits(engine_traits: "EngineTraits"):
# pylint: disable=import-outside-toplevel, too-many-branches # pylint: disable=import-outside-toplevel, too-many-branches
from lxml import html
import babel import babel
from searx.locales import language_tag from searx.locales import language_tag
@@ -100,7 +99,7 @@ def fetch_traits(engine_traits: "EngineTraits"):
if not resp.ok: if not resp.ok:
raise RuntimeError("Response from Yep languages is not OK.") raise RuntimeError("Response from Yep languages is not OK.")
doc = html.fromstring(resp.text) doc = resp.html()
url = eval_xpath_getindex(doc, "//script[contains(@src, 'PageApp')]/@src", index=0) url = eval_xpath_getindex(doc, "//script[contains(@src, 'PageApp')]/@src", index=0)
resp = get("https:" + extract_text(url), headers=headers, timeout=5) resp = get("https:" + extract_text(url), headers=headers, timeout=5)

View File

@@ -38,7 +38,6 @@ from datetime import datetime
from urllib.parse import quote from urllib.parse import quote
from flask_babel import gettext # pyright: ignore[reportUnknownVariableType] from flask_babel import gettext # pyright: ignore[reportUnknownVariableType]
from lxml import html
from searx.data import ENGINE_TRAITS from searx.data import ENGINE_TRAITS
from searx.enginelib.traits import EngineTraits from searx.enginelib.traits import EngineTraits
@@ -118,7 +117,7 @@ def request(query: str, params: "OnlineParams") -> None:
def response(resp: "SXNG_Response") -> EngineResults: def response(resp: "SXNG_Response") -> EngineResults:
res = EngineResults() res = EngineResults()
dom = html.fromstring(resp.text) dom = resp.html()
if domain_is_seized(dom): if domain_is_seized(dom):
raise SearxException(f"zlibrary domain is seized: {base_url}") raise SearxException(f"zlibrary domain is seized: {base_url}")
@@ -196,7 +195,7 @@ def fetch_traits(engine_traits: EngineTraits) -> None:
if not resp.ok: if not resp.ok:
raise RuntimeError("Response from zlibrary is not OK.") raise RuntimeError("Response from zlibrary is not OK.")
dom = html.fromstring(resp.text) dom = resp.html()
if domain_is_seized(dom): if domain_is_seized(dom):
raise RuntimeError(f"Response from zlibrary is not OK. ({base_url} seized)") raise RuntimeError(f"Response from zlibrary is not OK. ({base_url} seized)")

View File

@@ -2,6 +2,7 @@
# pylint: disable=missing-module-docstring,disable=missing-class-docstring,invalid-name # pylint: disable=missing-module-docstring,disable=missing-class-docstring,invalid-name
from collections import defaultdict from collections import defaultdict
import lxml.html
import mock import mock
from searx.engines import xpath from searx.engines import xpath
@@ -27,6 +28,7 @@ class TestXpathEngine(SearxTestCase):
</div> </div>
</div> </div>
""" """
empty_html = """<html></html>"""
def setUp(self): def setUp(self):
super().setUp() super().setUp()
@@ -65,10 +67,14 @@ class TestXpathEngine(SearxTestCase):
self.assertRaises(AttributeError, xpath.response, '') self.assertRaises(AttributeError, xpath.response, '')
self.assertRaises(AttributeError, xpath.response, '[]') self.assertRaises(AttributeError, xpath.response, '[]')
response = mock.Mock(text='<html></html>', status_code=200) response = mock.Mock(
text=self.empty_html, status_code=200, html=mock.Mock(return_value=lxml.html.fromstring(self.empty_html))
)
self.assertEqual(xpath.response(response), []) self.assertEqual(xpath.response(response), [])
response = mock.Mock(text=self.html, status_code=200) response = mock.Mock(
text=self.html, status_code=200, html=mock.Mock(return_value=lxml.html.fromstring(self.html))
)
results = xpath.response(response) results = xpath.response(response)
self.assertIsInstance(results, list) self.assertIsInstance(results, list)
self.assertEqual(len(results), 2) self.assertEqual(len(results), 2)
@@ -107,10 +113,16 @@ class TestXpathEngine(SearxTestCase):
self.assertRaises(AttributeError, xpath.response, '') self.assertRaises(AttributeError, xpath.response, '')
self.assertRaises(AttributeError, xpath.response, '[]') self.assertRaises(AttributeError, xpath.response, '[]')
response = mock.Mock(text='<html></html>', status_code=200) response = mock.Mock(
text=self.empty_html, status_code=200, html=mock.Mock(return_value=lxml.html.fromstring(self.empty_html))
)
self.assertEqual(xpath.response(response), []) self.assertEqual(xpath.response(response), [])
response = mock.Mock(text=self.html, status_code=200) response = mock.Mock(
text=self.html,
status_code=200,
html=mock.Mock(return_value=lxml.html.fromstring(self.html)),
)
results = xpath.response(response) results = xpath.response(response)
self.assertIsInstance(results, list) self.assertIsInstance(results, list)
self.assertEqual(len(results), 2) self.assertEqual(len(results), 2)