Spaces:
Running
Running
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 | |