Format: text/x-python
⬇ Download File (1.9 KB)
   1  from __future__ import annotations
   2  
   3  import re
   4  from html import unescape
   5  from typing import Any
   6  from urllib.parse import unquote
   7  
   8  from .exceptions import DuckDuckGoSearchException
   9  
  10  try:
  11      HAS_ORJSON = True
  12      import orjson
  13  except ImportError:
  14      HAS_ORJSON = False
  15      import json
  16  
  17  REGEX_STRIP_TAGS = re.compile("<.*?>")
  18  
  19  
  20  def json_dumps(obj: Any) -> str:
  21      try:
  22          return (
  23              orjson.dumps(obj, option=orjson.OPT_INDENT_2).decode()
  24              if HAS_ORJSON
  25              else json.dumps(obj, ensure_ascii=False, indent=2)
  26          )
  27      except Exception as ex:
  28          raise DuckDuckGoSearchException(f"{type(ex).__name__}: {ex}") from ex
  29  
  30  
  31  def json_loads(obj: str | bytes) -> Any:
  32      try:
  33          return orjson.loads(obj) if HAS_ORJSON else json.loads(obj)
  34      except Exception as ex:
  35          raise DuckDuckGoSearchException(f"{type(ex).__name__}: {ex}") from ex
  36  
  37  
  38  def _extract_vqd(html_bytes: bytes, keywords: str) -> str:
  39      """Extract vqd from html bytes."""
  40      for c1, c1_len, c2 in (
  41          (b'vqd="', 5, b'"'),
  42          (b"vqd=", 4, b"&"),
  43          (b"vqd='", 5, b"'"),
  44      ):
  45          try:
  46              start = html_bytes.index(c1) + c1_len
  47              end = html_bytes.index(c2, start)
  48              return html_bytes[start:end].decode()
  49          except ValueError:
  50              pass
  51      raise DuckDuckGoSearchException(f"_extract_vqd() {keywords=} Could not extract vqd.")
  52  
  53  
  54  def _normalize(raw_html: str) -> str:
  55      """Strip HTML tags from the raw_html string."""
  56      return unescape(REGEX_STRIP_TAGS.sub("", raw_html)) if raw_html else ""
  57  
  58  
  59  def _normalize_url(url: str) -> str:
  60      """Unquote URL and replace spaces with '+'."""
  61      return unquote(url).replace(" ", "+") if url else ""
  62  
  63  
  64  def _expand_proxy_tb_alias(proxy: str | None) -> str | None:
  65      """Expand "tb" to a full proxy URL if applicable."""
  66      return "socks5://127.0.0.1:9150" if proxy == "tb" else proxy
  67