""" search.py — free web search via DuckDuckGo HTML scraping. No API key, no signup, no cost. Slightly fragile (scraping), so kept isolated here in case the markup changes and needs a patch. """ import requests from bs4 import BeautifulSoup HEADERS = { "User-Agent": ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" ) } DDG_HTML_URL = "https://html.duckduckgo.com/html/" def ddg_search(query: str, max_results: int = 8): """Returns a list of {title, url, snippet} dicts.""" try: resp = requests.post( DDG_HTML_URL, data={"q": query}, headers=HEADERS, timeout=10, ) resp.raise_for_status() except requests.RequestException as e: return {"error": f"search request failed: {e}"} soup = BeautifulSoup(resp.text, "html.parser") results = [] for result in soup.select("div.result"): link_el = result.select_one("a.result__a") snippet_el = result.select_one("a.result__snippet") or result.select_one( "div.result__snippet" ) if not link_el: continue title = link_el.get_text(strip=True) url = link_el.get("href", "") snippet = snippet_el.get_text(strip=True) if snippet_el else "" if title and url: results.append({"title": title, "url": url, "snippet": snippet}) if len(results) >= max_results: break return results