Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,17 +3,32 @@ import requests
|
|
| 3 |
import json
|
| 4 |
import random
|
| 5 |
import logging
|
|
|
|
|
|
|
| 6 |
|
| 7 |
# Configure logging
|
| 8 |
-
logging.basicConfig(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
# List of SearXNG instances to try
|
| 11 |
SEARXNG_INSTANCES = [
|
| 12 |
-
"https://
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
# Add more instances here
|
|
|
|
|
|
|
| 14 |
]
|
| 15 |
|
| 16 |
-
def search_news(query, num_results=10):
|
| 17 |
# Shuffle the list of instances to distribute load
|
| 18 |
random.shuffle(SEARXNG_INSTANCES)
|
| 19 |
|
|
@@ -32,20 +47,44 @@ def search_news(query, num_results=10):
|
|
| 32 |
"count": num_results
|
| 33 |
# Omitted 'time_range'
|
| 34 |
}
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
return [], "Unable to fetch results from any SearXNG instance. Please try again later."
|
| 48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
def format_news_markdown(news_items, error=None):
|
| 50 |
if error:
|
| 51 |
return f"**Error:** {error}"
|
|
@@ -66,7 +105,7 @@ def format_news_markdown(news_items, error=None):
|
|
| 66 |
return formatted_results
|
| 67 |
|
| 68 |
def gradio_search_news(query, num_results):
|
| 69 |
-
news_items, error =
|
| 70 |
return format_news_markdown(news_items, error)
|
| 71 |
|
| 72 |
iface = gr.Interface(
|
|
|
|
| 3 |
import json
|
| 4 |
import random
|
| 5 |
import logging
|
| 6 |
+
import time
|
| 7 |
+
from functools import lru_cache
|
| 8 |
|
| 9 |
# Configure logging
|
| 10 |
+
logging.basicConfig(
|
| 11 |
+
level=logging.INFO,
|
| 12 |
+
format='%(asctime)s [%(levelname)s] %(message)s',
|
| 13 |
+
handlers=[
|
| 14 |
+
logging.FileHandler("searxng_search.log"),
|
| 15 |
+
logging.StreamHandler()
|
| 16 |
+
]
|
| 17 |
+
)
|
| 18 |
|
| 19 |
# List of SearXNG instances to try
|
| 20 |
SEARXNG_INSTANCES = [
|
| 21 |
+
"https://search.inetol.net",
|
| 22 |
+
"https://northboot.xyz",
|
| 23 |
+
"https://search.hbubli.cc",
|
| 24 |
+
"https://searx.tiekoetter.com",
|
| 25 |
+
"https://search.bus-hit.me",
|
| 26 |
# Add more instances here
|
| 27 |
+
"https://another-instance.com",
|
| 28 |
+
"https://yet-another-instance.com",
|
| 29 |
]
|
| 30 |
|
| 31 |
+
def search_news(query, num_results=10, max_retries=3):
|
| 32 |
# Shuffle the list of instances to distribute load
|
| 33 |
random.shuffle(SEARXNG_INSTANCES)
|
| 34 |
|
|
|
|
| 47 |
"count": num_results
|
| 48 |
# Omitted 'time_range'
|
| 49 |
}
|
| 50 |
+
|
| 51 |
+
retry_count = 0
|
| 52 |
+
backoff_time = 1 # Start with 1 second
|
| 53 |
+
|
| 54 |
+
while retry_count <= max_retries:
|
| 55 |
+
try:
|
| 56 |
+
response = requests.get(
|
| 57 |
+
f"{searxng_url}/search",
|
| 58 |
+
params=params,
|
| 59 |
+
headers=headers,
|
| 60 |
+
timeout=10
|
| 61 |
+
)
|
| 62 |
+
if response.status_code == 429:
|
| 63 |
+
# If rate limited, wait and retry
|
| 64 |
+
logging.warning(f"Rate limited by {searxng_url}. Retrying in {backoff_time} seconds...")
|
| 65 |
+
time.sleep(backoff_time)
|
| 66 |
+
retry_count += 1
|
| 67 |
+
backoff_time *= 2 # Exponential backoff
|
| 68 |
+
continue
|
| 69 |
+
response.raise_for_status()
|
| 70 |
+
results = response.json()
|
| 71 |
+
news_items = results.get("news", [])
|
| 72 |
+
if news_items:
|
| 73 |
+
logging.info(f"Success from instance: {searxng_url}")
|
| 74 |
+
return news_items, None
|
| 75 |
+
else:
|
| 76 |
+
logging.info(f"No results from {searxng_url}")
|
| 77 |
+
break # Move to the next instance
|
| 78 |
+
except requests.RequestException as e:
|
| 79 |
+
logging.warning(f"Instance {searxng_url} failed: {e}")
|
| 80 |
+
break # Move to the next instance if a non-rate limit error occurs
|
| 81 |
+
|
| 82 |
return [], "Unable to fetch results from any SearXNG instance. Please try again later."
|
| 83 |
|
| 84 |
+
@lru_cache(maxsize=128)
|
| 85 |
+
def cached_search_news(query, num_results=10):
|
| 86 |
+
return search_news(query, num_results)
|
| 87 |
+
|
| 88 |
def format_news_markdown(news_items, error=None):
|
| 89 |
if error:
|
| 90 |
return f"**Error:** {error}"
|
|
|
|
| 105 |
return formatted_results
|
| 106 |
|
| 107 |
def gradio_search_news(query, num_results):
|
| 108 |
+
news_items, error = cached_search_news(query, int(num_results))
|
| 109 |
return format_news_markdown(news_items, error)
|
| 110 |
|
| 111 |
iface = gr.Interface(
|