alpinelinux.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. """`Alpine Linux binary packages`_. `Alpine Linux`_ is a Linux-based operation
  3. system designed to be small, simple and secure. Contrary to many other Linux
  4. distributions, it uses musl, BusyBox and OpenRC. Alpine is mostly used on
  5. servers and for Docker images.
  6. .. _Alpine Linux binary packages: https://pkgs.alpinelinux.org
  7. .. _Alpine Linux: https://www.alpinelinux.org
  8. """
  9. import re
  10. from urllib.parse import urlencode
  11. from lxml import html
  12. from dateutil import parser
  13. from searx.utils import eval_xpath, eval_xpath_list, extract_text
  14. about = {
  15. 'website': 'https://www.alpinelinux.org',
  16. 'wikidata_id': 'Q4033826',
  17. 'use_official_api': False,
  18. 'official_api_documentation': None,
  19. 'require_api_key': False,
  20. 'results': 'HTML',
  21. }
  22. paging = True
  23. categories = ['packages', 'it']
  24. base_url = "https://pkgs.alpinelinux.org"
  25. alpine_arch = 'x86_64'
  26. """Kernel architecture: ``x86_64``, ``x86``, ``aarch64``, ``armhf``,
  27. ``ppc64le``, ``s390x``, ``armv7`` or ``riscv64``"""
  28. ARCH_RE = re.compile("x86_64|x86|aarch64|armhf|ppc64le|s390x|armv7|riscv64")
  29. """Regular expression to match supported architectures in the query string."""
  30. def request(query, params):
  31. query_arch = ARCH_RE.search(query)
  32. if query_arch:
  33. query_arch = query_arch.group(0)
  34. query = query.replace(query_arch, '').strip()
  35. args = {
  36. # use wildcards to match more than just packages with the exact same
  37. # name as the query
  38. 'name': f"*{query}*",
  39. 'page': params['pageno'],
  40. 'arch': query_arch or alpine_arch,
  41. }
  42. params['url'] = f"{base_url}/packages?{urlencode(args)}"
  43. return params
  44. def response(resp):
  45. results = []
  46. doc = html.fromstring(resp.text)
  47. for result in eval_xpath_list(doc, "//table/tbody/tr"):
  48. if len(result.xpath("./td")) < 9:
  49. # skip non valid entries in the result table
  50. # e.g the "No item found..." message
  51. continue
  52. results.append(
  53. {
  54. 'template': 'packages.html',
  55. 'url': base_url + extract_text(eval_xpath(result, './td[contains(@class, "package")]/a/@href')),
  56. 'title': extract_text(eval_xpath(result, './td[contains(@class, "package")]')),
  57. 'package_name': extract_text(eval_xpath(result, './td[contains(@class, "package")]')),
  58. 'publishedDate': parser.parse(extract_text(eval_xpath(result, './td[contains(@class, "bdate")]'))),
  59. 'version': extract_text(eval_xpath(result, './td[contains(@class, "version")]')),
  60. 'homepage': extract_text(eval_xpath(result, './td[contains(@class, "url")]/a/@href')),
  61. 'maintainer': extract_text(eval_xpath(result, './td[contains(@class, "maintainer")]')),
  62. 'license_name': extract_text(eval_xpath(result, './td[contains(@class, "license")]')),
  63. 'tags': [extract_text(eval_xpath(result, './td[contains(@class, "repo")]'))],
  64. }
  65. )
  66. return results