on master help sign in
[mod] move extract_text, extract_url to searx.utils
2006eb4Alexandre Flament
searx/engines/1337x.py+1−2
@@ -1,7 +1,6 @@
1from urllib.parse import quote, urljoin
1from urllib.parse import quote, urljoin
2from lxml import html
2from lxml import html
3−from searx.engines.xpath import extract_text
3+from searx.utils import extract_text, get_torrent_size
4−from searx.utils import get_torrent_size
5
4
6
5
7url = 'https://1337x.to/'
6url = 'https://1337x.to/'
searx/engines/acgsou.py+1−2
@@ -11,8 +11,7 @@
11
11
12from urllib.parse import urlencode
12from urllib.parse import urlencode
13from lxml import html
13from lxml import html
14−from searx.engines.xpath import extract_text
14+from searx.utils import extract_text, get_torrent_size, int_or_zero
15−from searx.utils import get_torrent_size, int_or_zero
16
15
17# engine dependent config
16# engine dependent config
18categories = ['files', 'images', 'videos', 'music']
17categories = ['files', 'images', 'videos', 'music']
searx/engines/apkmirror.py+1−1
@@ -11,7 +11,7 @@
11
11
12from urllib.parse import urlencode
12from urllib.parse import urlencode
13from lxml import html
13from lxml import html
14−from searx.engines.xpath import extract_text
14+from searx.utils import extract_text
15
15
16
16
17# engine dependent config
17# engine dependent config
searx/engines/archlinux.py+1−1
@@ -13,7 +13,7 @@
13
13
14from urllib.parse import urlencode, urljoin
14from urllib.parse import urlencode, urljoin
15from lxml import html
15from lxml import html
16−from searx.engines.xpath import extract_text
16+from searx.utils import extract_text
17
17
18# engine dependent config
18# engine dependent config
19categories = ['it']
19categories = ['it']
searx/engines/bing.py+1−2
@@ -17,8 +17,7 @@ import re
17from urllib.parse import urlencode
17from urllib.parse import urlencode
18from lxml import html
18from lxml import html
19from searx import logger, utils
19from searx import logger, utils
20−from searx.engines.xpath import extract_text
21−from searx.utils import match_language, gen_useragent, eval_xpath
20+from searx.utils import extract_text, match_language, gen_useragent, eval_xpath
22
21
23logger = logger.getChild('bing engine')
22logger = logger.getChild('bing engine')
24
23
searx/engines/btdigg.py+1−2
@@ -13,8 +13,7 @@
13from lxml import html
13from lxml import html
14from operator import itemgetter
14from operator import itemgetter
15from urllib.parse import quote, urljoin
15from urllib.parse import quote, urljoin
16−from searx.engines.xpath import extract_text
16+from searx.utils import extract_text, get_torrent_size
17−from searx.utils import get_torrent_size
18
17
19# engine dependent config
18# engine dependent config
20categories = ['videos', 'music', 'files']
19categories = ['videos', 'music', 'files']
searx/engines/deviantart.py+1−1
@@ -15,7 +15,7 @@
15from lxml import html
15from lxml import html
16import re
16import re
17from urllib.parse import urlencode
17from urllib.parse import urlencode
18−from searx.engines.xpath import extract_text
18+from searx.utils import extract_text
19
19
20
20
21# engine dependent config
21# engine dependent config
searx/engines/digbt.py+1−2
@@ -12,8 +12,7 @@
12
12
13from urllib.parse import urljoin
13from urllib.parse import urljoin
14from lxml import html
14from lxml import html
15−from searx.engines.xpath import extract_text
15+from searx.utils import extract_text, get_torrent_size
16−from searx.utils import get_torrent_size
17
16
18
17
19categories = ['videos', 'music', 'files']
18categories = ['videos', 'music', 'files']
searx/engines/doku.py+1−2
@@ -11,8 +11,7 @@
11
11
12from urllib.parse import urlencode
12from urllib.parse import urlencode
13from lxml.html import fromstring
13from lxml.html import fromstring
14−from searx.engines.xpath import extract_text
14+from searx.utils import extract_text, eval_xpath
15−from searx.utils import eval_xpath
16
15
17# engine dependent config
16# engine dependent config
18categories = ['general'] # TODO , 'images', 'music', 'videos', 'files'
17categories = ['general'] # TODO , 'images', 'music', 'videos', 'files'
searx/engines/duckduckgo.py+1−2
@@ -16,9 +16,8 @@
16from lxml.html import fromstring
16from lxml.html import fromstring
17from json import loads
17from json import loads
18from urllib.parse import urlencode
18from urllib.parse import urlencode
19−from searx.engines.xpath import extract_text
20from searx.poolrequests import get
19from searx.poolrequests import get
21−from searx.utils import match_language, eval_xpath
20+from searx.utils import extract_text, match_language, eval_xpath
22
21
23# engine dependent config
22# engine dependent config
24categories = ['general']
23categories = ['general']
searx/engines/duckduckgo_definitions.py+1−2
@@ -13,9 +13,8 @@ import json
13from urllib.parse import urlencode
13from urllib.parse import urlencode
14from lxml import html
14from lxml import html
15from re import compile
15from re import compile
16−from searx.engines.xpath import extract_text
17from searx.engines.duckduckgo import _fetch_supported_languages, supported_languages_url, language_aliases
16from searx.engines.duckduckgo import _fetch_supported_languages, supported_languages_url, language_aliases
18−from searx.utils import html_to_text, match_language
17+from searx.utils import extract_text, html_to_text, match_language
19
18
20url = 'https://api.duckduckgo.com/'\
19url = 'https://api.duckduckgo.com/'\
21 + '?{query}&format=json&pretty=0&no_redirect=1&d=1'
20 + '?{query}&format=json&pretty=0&no_redirect=1&d=1'
searx/engines/duckduckgo_images.py+1−1
@@ -15,12 +15,12 @@
15
15
16from json import loads
16from json import loads
17from urllib.parse import urlencode
17from urllib.parse import urlencode
18−from searx.engines.xpath import extract_text
19from searx.engines.duckduckgo import (
18from searx.engines.duckduckgo import (
20 _fetch_supported_languages, supported_languages_url,
19 _fetch_supported_languages, supported_languages_url,
21 get_region_code, language_aliases
20 get_region_code, language_aliases
22)
21)
23from searx.poolrequests import get
22from searx.poolrequests import get
23+from searx.utils import extract_text
24
24
25# engine dependent config
25# engine dependent config
26categories = ['images']
26categories = ['images']
searx/engines/duden.py+1−2
@@ -11,8 +11,7 @@
11from lxml import html, etree
11from lxml import html, etree
12import re
12import re
13from urllib.parse import quote, urljoin
13from urllib.parse import quote, urljoin
14−from searx.engines.xpath import extract_text
14+from searx.utils import extract_text, eval_xpath
15−from searx.utils import eval_xpath
16from searx import logger
15from searx import logger
17
16
18categories = ['general']
17categories = ['general']
searx/engines/etools.py+1−2
@@ -11,8 +11,7 @@
11
11
12from lxml import html
12from lxml import html
13from urllib.parse import quote
13from urllib.parse import quote
14−from searx.engines.xpath import extract_text
14+from searx.utils import extract_text, eval_xpath
15−from searx.utils import eval_xpath
16
15
17categories = ['general']
16categories = ['general']
18paging = False
17paging = False
searx/engines/fdroid.py+1−1
@@ -11,7 +11,7 @@
11
11
12from urllib.parse import urlencode
12from urllib.parse import urlencode
13from lxml import html
13from lxml import html
14−from searx.engines.xpath import extract_text
14+from searx.utils import extract_text
15
15
16# engine dependent config
16# engine dependent config
17categories = ['files']
17categories = ['files']
searx/engines/framalibre.py+1−1
@@ -13,7 +13,7 @@
13from html import escape
13from html import escape
14from urllib.parse import urljoin, urlencode
14from urllib.parse import urljoin, urlencode
15from lxml import html
15from lxml import html
16−from searx.engines.xpath import extract_text
16+from searx.utils import extract_text
17
17
18# engine dependent config
18# engine dependent config
19categories = ['it']
19categories = ['it']
searx/engines/gentoo.py+1−1
@@ -13,7 +13,7 @@
13
13
14from urllib.parse import urlencode, urljoin
14from urllib.parse import urlencode, urljoin
15from lxml import html
15from lxml import html
16−from searx.engines.xpath import extract_text
16+from searx.utils import extract_text
17
17
18# engine dependent config
18# engine dependent config
19categories = ['it']
19categories = ['it']
searx/engines/google.py+1−2
@@ -21,9 +21,8 @@ Definitions`_.
21from urllib.parse import urlencode, urlparse
21from urllib.parse import urlencode, urlparse
22from lxml import html
22from lxml import html
23from flask_babel import gettext
23from flask_babel import gettext
24−from searx.engines.xpath import extract_text
25from searx import logger
24from searx import logger
26−from searx.utils import match_language, eval_xpath
25+from searx.utils import match_language, extract_text, eval_xpath
27
26
28logger = logger.getChild('google engine')
27logger = logger.getChild('google engine')
29
28
searx/engines/google_images.py+1−2
@@ -28,8 +28,7 @@ from urllib.parse import urlencode, urlparse, unquote
28from lxml import html
28from lxml import html
29from flask_babel import gettext
29from flask_babel import gettext
30from searx import logger
30from searx import logger
31−from searx.utils import eval_xpath
31+from searx.utils import extract_text, eval_xpath
32−from searx.engines.xpath import extract_text
33
32
34# pylint: disable=unused-import
33# pylint: disable=unused-import
35from searx.engines.google import (
34from searx.engines.google import (
searx/engines/google_videos.py+1−1
@@ -14,7 +14,7 @@ from datetime import date, timedelta
14from json import loads
14from json import loads
15from urllib.parse import urlencode
15from urllib.parse import urlencode
16from lxml import html
16from lxml import html
17−from searx.engines.xpath import extract_text
17+from searx.utils import extract_text
18import re
18import re
19
19
20# engine dependent config
20# engine dependent config
searx/engines/ina.py+1−1
@@ -16,7 +16,7 @@ from urllib.parse import urlencode
16from lxml import html
16from lxml import html
17from dateutil import parser
17from dateutil import parser
18from html.parser import HTMLParser
18from html.parser import HTMLParser
19−from searx.engines.xpath import extract_text
19+from searx.utils import extract_text
20
20
21
21
22# engine dependent config
22# engine dependent config
searx/engines/kickass.py+1−2
@@ -13,8 +13,7 @@
13from lxml import html
13from lxml import html
14from operator import itemgetter
14from operator import itemgetter
15from urllib.parse import quote, urljoin
15from urllib.parse import quote, urljoin
16−from searx.engines.xpath import extract_text
17−from searx.utils import get_torrent_size, convert_str_to_int
16+from searx.utils import extract_text, get_torrent_size, convert_str_to_int
18
17
19# engine dependent config
18# engine dependent config
20categories = ['videos', 'music', 'files']
19categories = ['videos', 'music', 'files']
searx/engines/nyaa.py+1−2
@@ -11,8 +11,7 @@
11
11
12from lxml import html
12from lxml import html
13from urllib.parse import urlencode
13from urllib.parse import urlencode
14−from searx.engines.xpath import extract_text
14+from searx.utils import extract_text, get_torrent_size, int_or_zero
15−from searx.utils import get_torrent_size, int_or_zero
16
15
17# engine dependent config
16# engine dependent config
18categories = ['files', 'images', 'videos', 'music']
17categories = ['files', 'images', 'videos', 'music']
searx/engines/piratebay.py+1−2
@@ -13,8 +13,7 @@ from datetime import datetime
13from operator import itemgetter
13from operator import itemgetter
14
14
15from urllib.parse import quote, urljoin
15from urllib.parse import quote, urljoin
16−from searx.engines.xpath import extract_text
16+from searx.utils import extract_text, get_torrent_size
17−from searx.utils import get_torrent_size
18
17
19# engine dependent config
18# engine dependent config
20categories = ["videos", "music", "files"]
19categories = ["videos", "music", "files"]
searx/engines/seedpeer.py+1−1
@@ -12,7 +12,7 @@ from lxml import html
12from json import loads
12from json import loads
13from operator import itemgetter
13from operator import itemgetter
14from urllib.parse import quote, urljoin
14from urllib.parse import quote, urljoin
15−from searx.engines.xpath import extract_text
15+from searx.utils import extract_text
16
16
17
17
18url = 'https://seedpeer.me/'
18url = 'https://seedpeer.me/'
searx/engines/stackoverflow.py+1−1
@@ -12,7 +12,7 @@
12
12
13from urllib.parse import urlencode, urljoin
13from urllib.parse import urlencode, urljoin
14from lxml import html
14from lxml import html
15−from searx.engines.xpath import extract_text
15+from searx.utils import extract_text
16
16
17# engine dependent config
17# engine dependent config
18categories = ['it']
18categories = ['it']
searx/engines/startpage.py+1−2
@@ -17,9 +17,8 @@ import re
17from unicodedata import normalize, combining
17from unicodedata import normalize, combining
18from babel import Locale
18from babel import Locale
19from babel.localedata import locale_identifiers
19from babel.localedata import locale_identifiers
20−from searx.engines.xpath import extract_text
21from searx.languages import language_codes
20from searx.languages import language_codes
22−from searx.utils import eval_xpath, match_language
21+from searx.utils import extract_text, eval_xpath, match_language
23
22
24# engine dependent config
23# engine dependent config
25categories = ['general']
24categories = ['general']
searx/engines/tokyotoshokan.py+1−2
@@ -13,9 +13,8 @@
13import re
13import re
14from urllib.parse import urlencode
14from urllib.parse import urlencode
15from lxml import html
15from lxml import html
16−from searx.engines.xpath import extract_text
17from datetime import datetime
16from datetime import datetime
18−from searx.utils import get_torrent_size, int_or_zero
17+from searx.utils import extract_text, get_torrent_size, int_or_zero
19
18
20# engine dependent config
19# engine dependent config
21categories = ['files', 'videos', 'music']
20categories = ['files', 'videos', 'music']
searx/engines/torrentz.py+1−2
@@ -15,8 +15,7 @@ import re
15from urllib.parse import urlencode
15from urllib.parse import urlencode
16from lxml import html
16from lxml import html
17from datetime import datetime
17from datetime import datetime
18−from searx.engines.xpath import extract_text
18+from searx.utils import extract_text, get_torrent_size
19−from searx.utils import get_torrent_size
20
19
21# engine dependent config
20# engine dependent config
22categories = ['files', 'videos', 'music']
21categories = ['files', 'videos', 'music']
searx/engines/twitter.py+1−1
@@ -15,7 +15,7 @@
15from urllib.parse import urlencode, urljoin
15from urllib.parse import urlencode, urljoin
16from lxml import html
16from lxml import html
17from datetime import datetime
17from datetime import datetime
18−from searx.engines.xpath import extract_text
18+from searx.utils import extract_text
19
19
20# engine dependent config
20# engine dependent config
21categories = ['social media']
21categories = ['social media']
searx/engines/wikidata.py+1−2
@@ -13,9 +13,8 @@
13
13
14from searx import logger
14from searx import logger
15from searx.poolrequests import get
15from searx.poolrequests import get
16−from searx.engines.xpath import extract_text
17from searx.engines.wikipedia import _fetch_supported_languages, supported_languages_url
16from searx.engines.wikipedia import _fetch_supported_languages, supported_languages_url
18−from searx.utils import match_language, eval_xpath
17+from searx.utils import extract_text, match_language, eval_xpath
19
18
20from urllib.parse import urlencode
19from urllib.parse import urlencode
21from json import loads
20from json import loads
searx/engines/www1x.py+1−1
@@ -12,7 +12,7 @@
12
12
13from lxml import html
13from lxml import html
14from urllib.parse import urlencode, urljoin
14from urllib.parse import urlencode, urljoin
15−from searx.engines.xpath import extract_text
15+from searx.utils import extract_text
16
16
17# engine dependent config
17# engine dependent config
18categories = ['images']
18categories = ['images']
searx/engines/xpath.py+2−73
@@ -1,7 +1,6 @@
1−from urllib.parse import unquote, urlencode, urljoin, urlparse
2from lxml import html
1from lxml import html
3−from lxml.etree import _ElementStringResult, _ElementUnicodeResult
2+from urllib.parse import urlencode
4−from searx.utils import html_to_text, eval_xpath
3+from searx.utils import extract_text, extract_url, eval_xpath
5
4
6search_url = None
5search_url = None
7url_xpath = None
6url_xpath = None
@@ -21,76 +20,6 @@ page_size = 1
21first_page_num = 1
20first_page_num = 1
22
21
23
22
24−'''
25−if xpath_results is list, extract the text from each result and concat the list
26−if xpath_results is a xml element, extract all the text node from it
27− ( text_content() method from lxml )
28−if xpath_results is a string element, then it's already done
29−'''
30−
31−
32−def extract_text(xpath_results):
33− if type(xpath_results) == list:
34− # it's list of result : concat everything using recursive call
35− result = ''
36− for e in xpath_results:
37− result = result + extract_text(e)
38− return result.strip()
39− elif type(xpath_results) in [_ElementStringResult, _ElementUnicodeResult]:
40− # it's a string
41− return ''.join(xpath_results)
42− else:
43− # it's a element
44− text = html.tostring(
45− xpath_results, encoding='unicode', method='text', with_tail=False
46− )
47− text = text.strip().replace('\n', ' ')
48− return ' '.join(text.split())
49−
50−
51−def extract_url(xpath_results, search_url):
52− if xpath_results == []:
53− raise Exception('Empty url resultset')
54− url = extract_text(xpath_results)
55−
56− if url.startswith('//'):
57− # add http or https to this kind of url //example.com/
58− parsed_search_url = urlparse(search_url)
59− url = '{0}:{1}'.format(parsed_search_url.scheme or 'http', url)
60− elif url.startswith('/'):
61− # fix relative url to the search engine
62− url = urljoin(search_url, url)
63−
64− # fix relative urls that fall through the crack
65− if '://' not in url:
66− url = urljoin(search_url, url)
67−
68− # normalize url
69− url = normalize_url(url)
70−
71− return url
72−
73−
74−def normalize_url(url):
75− parsed_url = urlparse(url)
76−
77− # add a / at this end of the url if there is no path
78− if not parsed_url.netloc:
79− raise Exception('Cannot parse url')
80− if not parsed_url.path:
81− url += '/'
82−
83− # FIXME : hack for yahoo
84− if parsed_url.hostname == 'search.yahoo.com'\
85− and parsed_url.path.startswith('/r'):
86− p = parsed_url.path
87− mark = p.find('/**')
88− if mark != -1:
89− return unquote(p[mark + 3:]).decode()
90−
91− return url
92−
93−
94def request(query, params):
23def request(query, params):
95 query = urlencode({'q': query})[2:]
24 query = urlencode({'q': query})[2:]
96
25
searx/engines/yahoo.py+1−2
@@ -13,8 +13,7 @@
13
13
14from urllib.parse import unquote, urlencode
14from urllib.parse import unquote, urlencode
15from lxml import html
15from lxml import html
16−from searx.engines.xpath import extract_text, extract_url
16+from searx.utils import extract_text, extract_url, match_language, eval_xpath
17−from searx.utils import match_language, eval_xpath
18
17
19# engine dependent config
18# engine dependent config
20categories = ['general']
19categories = ['general']
searx/engines/yahoo_news.py+1−2
@@ -13,12 +13,11 @@ import re
13from datetime import datetime, timedelta
13from datetime import datetime, timedelta
14from urllib.parse import urlencode
14from urllib.parse import urlencode
15from lxml import html
15from lxml import html
16−from searx.engines.xpath import extract_text, extract_url
17from searx.engines.yahoo import (
16from searx.engines.yahoo import (
18 parse_url, _fetch_supported_languages, supported_languages_url, language_aliases
17 parse_url, _fetch_supported_languages, supported_languages_url, language_aliases
19)
18)
20from dateutil import parser
19from dateutil import parser
21−from searx.utils import match_language
20+from searx.utils import extract_text, extract_url, match_language
22
21
23# engine dependent config
22# engine dependent config
24categories = ['news']
23categories = ['news']
searx/engines/yggtorrent.py+1−2
@@ -12,8 +12,7 @@ from lxml import html
12from operator import itemgetter
12from operator import itemgetter
13from datetime import datetime
13from datetime import datetime
14from urllib.parse import quote
14from urllib.parse import quote
15−from searx.engines.xpath import extract_text
15+from searx.utils import extract_text, get_torrent_size
16−from searx.utils import get_torrent_size
17from searx.poolrequests import get as http_get
16from searx.poolrequests import get as http_get
18
17
19# engine dependent config
18# engine dependent config
searx/engines/youtube_noapi.py+1−2
@@ -11,8 +11,7 @@
11from functools import reduce
11from functools import reduce
12from json import loads
12from json import loads
13from urllib.parse import quote_plus
13from urllib.parse import quote_plus
14−from searx.engines.xpath import extract_text
14+from searx.utils import extract_text, list_get
15−from searx.utils import list_get
16
15
17# engine dependent config
16# engine dependent config
18categories = ['videos', 'music']
17categories = ['videos', 'music']
searx/utils.py+73−1
@@ -10,9 +10,13 @@ from os.path import splitext, join
10from io import open
10from io import open
11from random import choice
11from random import choice
12from html.parser import HTMLParser
12from html.parser import HTMLParser
13+from urllib.parse import urljoin, urlparse, unquote
14+
15+from lxml import html
13−from lxml.etree import XPath
16+from lxml.etree import XPath, _ElementStringResult, _ElementUnicodeResult
14from babel.core import get_global
17from babel.core import get_global
15
18
19+
16from searx import settings
20from searx import settings
17from searx.version import VERSION_STRING
21from searx.version import VERSION_STRING
18from searx.languages import language_codes
22from searx.languages import language_codes
@@ -106,6 +110,74 @@ def html_to_text(html):
106 return s.get_text()
110 return s.get_text()
107
111
108
112
113+def extract_text(xpath_results):
114+ '''
115+ if xpath_results is list, extract the text from each result and concat the list
116+ if xpath_results is a xml element, extract all the text node from it
117+ ( text_content() method from lxml )
118+ if xpath_results is a string element, then it's already done
119+ '''
120+ if type(xpath_results) == list:
121+ # it's list of result : concat everything using recursive call
122+ result = ''
123+ for e in xpath_results:
124+ result = result + extract_text(e)
125+ return result.strip()
126+ elif type(xpath_results) in [_ElementStringResult, _ElementUnicodeResult]:
127+ # it's a string
128+ return ''.join(xpath_results)
129+ else:
130+ # it's a element
131+ text = html.tostring(
132+ xpath_results, encoding='unicode', method='text', with_tail=False
133+ )
134+ text = text.strip().replace('\n', ' ')
135+ return ' '.join(text.split())
136+
137+
138+def extract_url(xpath_results, search_url):
139+ if xpath_results == []:
140+ raise Exception('Empty url resultset')
141+ url = extract_text(xpath_results)
142+
143+ if url.startswith('//'):
144+ # add http or https to this kind of url //example.com/
145+ parsed_search_url = urlparse(search_url)
146+ url = '{0}:{1}'.format(parsed_search_url.scheme or 'http', url)
147+ elif url.startswith('/'):
148+ # fix relative url to the search engine
149+ url = urljoin(search_url, url)
150+
151+ # fix relative urls that fall through the crack
152+ if '://' not in url:
153+ url = urljoin(search_url, url)
154+
155+ # normalize url
156+ url = normalize_url(url)
157+
158+ return url
159+
160+
161+def normalize_url(url):
162+ parsed_url = urlparse(url)
163+
164+ # add a / at this end of the url if there is no path
165+ if not parsed_url.netloc:
166+ raise Exception('Cannot parse url')
167+ if not parsed_url.path:
168+ url += '/'
169+
170+ # FIXME : hack for yahoo
171+ if parsed_url.hostname == 'search.yahoo.com'\
172+ and parsed_url.path.startswith('/r'):
173+ p = parsed_url.path
174+ mark = p.find('/**')
175+ if mark != -1:
176+ return unquote(p[mark + 3:]).decode()
177+
178+ return url
179+
180+
109def dict_subset(d, properties):
181def dict_subset(d, properties):
110 result = {}
182 result = {}
111 for k in properties:
183 for k in properties:
tests/unit/test_utils.py+45−4
@@ -1,4 +1,7 @@
1# -*- coding: utf-8 -*-
1# -*- coding: utf-8 -*-
2+import lxml.etree
3+from lxml import html
4+
2from searx.testing import SearxTestCase
5from searx.testing import SearxTestCase
3from searx import utils
6from searx import utils
4
7
@@ -16,7 +19,30 @@ class TestUtils(SearxTestCase):
16 self.assertTrue(utils.searx_useragent().startswith('searx'))
19 self.assertTrue(utils.searx_useragent().startswith('searx'))
17
20
18 def test_html_to_text(self):
21 def test_html_to_text(self):
19− html = """
22+ html_str = """
23+ <a href="/testlink" class="link_access_account">
24+ <style>
25+ .toto {
26+ color: red;
27+ }
28+ </style>
29+ <span class="toto">
30+ <span>
31+ <img src="test.jpg" />
32+ </span>
33+ </span>
34+ <span class="titi">
35+ Test text
36+ </span>
37+ <script>value='dummy';</script>
38+ </a>
39+ """
40+ self.assertIsInstance(utils.html_to_text(html_str), str)
41+ self.assertIsNotNone(utils.html_to_text(html_str))
42+ self.assertEqual(utils.html_to_text(html_str), "Test text")
43+
44+ def test_extract_text(self):
45+ html_str = """
20 <a href="/testlink" class="link_access_account">
46 <a href="/testlink" class="link_access_account">
21 <span class="toto">
47 <span class="toto">
22 <span>
48 <span>
@@ -28,9 +54,24 @@ class TestUtils(SearxTestCase):
28 </span>
54 </span>
29 </a>
55 </a>
30 """
56 """
31− self.assertIsInstance(utils.html_to_text(html), str)
57+ dom = html.fromstring(html_str)
32− self.assertIsNotNone(utils.html_to_text(html))
58+ self.assertEqual(utils.extract_text(dom), 'Test text')
59+ self.assertEqual(utils.extract_text(dom.xpath('//span')), 'Test text')
60+ self.assertEqual(utils.extract_text(dom.xpath('//img/@src')), 'test.jpg')
33− self.assertEqual(utils.html_to_text(html), "Test text")
61+ self.assertEqual(utils.extract_text(dom.xpath('//unexistingtag')), '')
62+
63+ def test_extract_url(self):
64+ def f(html_str, search_url):
65+ return utils.extract_url(html.fromstring(html_str), search_url)
66+ self.assertEqual(f('<span id="42">https://example.com</span>', 'http://example.com/'), 'https://example.com/')
67+ self.assertEqual(f('https://example.com', 'http://example.com/'), 'https://example.com/')
68+ self.assertEqual(f('//example.com', 'http://example.com/'), 'http://example.com/')
69+ self.assertEqual(f('//example.com', 'https://example.com/'), 'https://example.com/')
70+ self.assertEqual(f('/path?a=1', 'https://example.com'), 'https://example.com/path?a=1')
71+ with self.assertRaises(lxml.etree.ParserError):
72+ f('', 'https://example.com')
73+ with self.assertRaises(Exception):
74+ utils.extract_url([], 'https://example.com')
34
75
35 def test_html_to_text_invalid(self):
76 def test_html_to_text_invalid(self):
36 html = '<p><b>Lorem ipsum</i>dolor sit amet</p>'
77 html = '<p><b>Lorem ipsum</i>dolor sit amet</p>'