File size: 3,893 Bytes
5d3056e
21eada5
4fef53c
f474072
bf857f3
feedb11
21eada5
feedb11
4fef53c
f474072
feedb11
f474072
4fef53c
f474072
 
 
4fef53c
 
 
feedb11
4fef53c
 
feedb11
f474072
feedb11
 
 
 
f474072
 
 
feedb11
 
 
 
b0957f0
f474072
feedb11
4fef53c
b0957f0
feedb11
f474072
b0957f0
feedb11
f474072
 
 
4fef53c
b0957f0
feedb11
f474072
b0957f0
feedb11
4fef53c
feedb11
 
 
f474072
 
 
4fef53c
b0957f0
4fef53c
b0957f0
f474072
b0957f0
9460907
b0957f0
 
 
 
 
f474072
21eada5
feedb11
 
 
21eada5
feedb11
21eada5
f474072
feedb11
 
f474072
 
 
 
feedb11
 
f474072
feedb11
 
 
 
 
b0957f0
feedb11
 
 
 
 
 
b0957f0
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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