import gradio as gr import pandas as pd import requests import tempfile from docx import Document from datetime import datetime # DuckDuckGo API search def search_api(query): if not query.strip(): return pd.DataFrame([{"Rank": "", "Title": "Please enter a valid search query.", "URL": ""}]) url = f"https://api.duckduckgo.com/?q={query}&format=json&no_redirect=1" try: response = requests.get(url) response.raise_for_status() data = response.json() related_topics = data.get("RelatedTopics", []) results = [] for topic in related_topics: if "Text" in topic and "FirstURL" in topic: results.append({"Title": topic["Text"], "URL": topic["FirstURL"]}) elif "Topics" in topic: for sub in topic["Topics"]: if "Text" in sub and "FirstURL" in sub: results.append({"Title": sub["Text"], "URL": sub["FirstURL"]}) if not results: results.append({"Title": "No results found.", "URL": ""}) for i, r in enumerate(results): r["Rank"] = i + 1 return pd.DataFrame(results)[["Rank", "Title", "URL"]] except Exception as e: return pd.DataFrame([{"Rank": "", "Title": "Error fetching results.", "URL": str(e)}]) # Export CSV safely def export_csv(results, query): if results is None or results.empty: return "" timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") with tempfile.NamedTemporaryFile(delete=False, suffix=".csv", mode="w", newline='', encoding="utf-8") as tmp: results.to_csv(tmp.name, index=False) return tmp.name # Export DOCX safely def export_docx(results, query): if results is None or results.empty: return "" timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") doc = Document() doc.add_heading(f"Search Results for: {query}", 0) for i, row in results.iterrows(): doc.add_paragraph(f"{row['Rank']}. {row['Title']}\n{row['URL']}") with tempfile.NamedTemporaryFile(delete=False, suffix=".docx") as tmp: doc.save(tmp.name) return tmp.name # Gradio UI with gr.Blocks() as demo: gr.Markdown("## 🔎 Smart DuckDuckGo Search & Export App") gr.Markdown(""" This app lets you search DuckDuckGo and export the results as a **CSV or Word DOCX** file. ### Instructions: 1. Enter a search topic (e.g., "climate change"). 2. Click **Search** to fetch results from DuckDuckGo. 3. View and click links directly. 4. Export results using the buttons below. """) query = gr.Textbox(label="Search Query", placeholder="Enter topic...") status = gr.Markdown("") search_btn = gr.Button("🔍 Search Now") results_display = gr.Dataframe(headers=["Rank", "Title", "URL"], label="Search Results", interactive=False) with gr.Row(): export_csv_btn = gr.Button("⬇️ Export CSV") export_docx_btn = gr.Button("⬇️ Export DOCX") csv_file = gr.File(label="Download CSV") docx_file = gr.File(label="Download DOCX") def handle_search(q): status_msg = f"Searching DuckDuckGo for **{q}**..." df = search_api(q) if "Error" in df.iloc[0]["Title"]: status_msg = f"❌ Error: {df.iloc[0]['URL']}" elif "Please enter" in df.iloc[0]["Title"]: status_msg = "⚠️ Please enter a search term." else: status_msg = f"✅ Found {len(df)} results for: **{q}**" return df, status_msg search_btn.click(fn=handle_search, inputs=query, outputs=[results_display, status]) export_csv_btn.click(fn=export_csv, inputs=[results_display, query], outputs=csv_file) export_docx_btn.click(fn=export_docx, inputs=[results_display, query], outputs=docx_file) demo.launch() # DO NOT set share=True on Hugging Face Spaces