Spaces:
Sleeping
Sleeping
Create src/chimera/api_clients/serp_client.py
Browse files
src/chimera/api_clients/serp_client.py
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# src/chimera/api_clients/serp_client.py
|
2 |
+
import httpx # Using httpx for async requests
|
3 |
+
from ..config import SERPAPI_API_KEY # Assuming SerpApi service
|
4 |
+
from ..utils.logging_config import logger
|
5 |
+
import json
|
6 |
+
|
7 |
+
# If using the official serpapi library:
|
8 |
+
# from serpapi import GoogleSearch
|
9 |
+
# Note: The official library might be synchronous. You might need
|
10 |
+
# asyncio.to_thread like in the Gemini example if using it in async code.
|
11 |
+
|
12 |
+
# Example using httpx for a generic SERP API endpoint (adjust URL/params)
|
13 |
+
# This is a simplified example assuming a REST API like SerpApi.
|
14 |
+
# You'd replace this with the actual client/method for your chosen service.
|
15 |
+
|
16 |
+
async def search_google(query: str, num_results=5, location=None) -> dict:
|
17 |
+
"""
|
18 |
+
Performs a search using a SERP API (example uses SerpApi parameters).
|
19 |
+
"""
|
20 |
+
if not SERPAPI_API_KEY:
|
21 |
+
logger.error("SERP API Key not configured.")
|
22 |
+
return {"error": "SERP API Key not configured."}
|
23 |
+
|
24 |
+
params = {
|
25 |
+
"q": query,
|
26 |
+
"api_key": SERPAPI_API_KEY,
|
27 |
+
"num": str(num_results), # API might expect string
|
28 |
+
# Add other parameters like location, gl (country), hl (language) as needed
|
29 |
+
# "location": location,
|
30 |
+
"engine": "google", # Specify search engine for APIs like SerpApi
|
31 |
+
}
|
32 |
+
if location:
|
33 |
+
params["location"] = location
|
34 |
+
|
35 |
+
# Adjust URL for your specific SERP provider
|
36 |
+
SEARCH_URL = "https://serpapi.com/search"
|
37 |
+
|
38 |
+
try:
|
39 |
+
async with httpx.AsyncClient() as client:
|
40 |
+
logger.info(f"Querying SERP API for: {query}")
|
41 |
+
response = await client.get(SEARCH_URL, params=params, timeout=20.0) # Add timeout
|
42 |
+
response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
|
43 |
+
|
44 |
+
results = response.json()
|
45 |
+
logger.info(f"Received {len(results.get('organic_results', []))} results from SERP API.")
|
46 |
+
# You might want to process/filter results here before returning
|
47 |
+
return results # Return the raw JSON or processed data
|
48 |
+
|
49 |
+
except httpx.HTTPStatusError as e:
|
50 |
+
logger.error(f"SERP API request failed: {e.response.status_code} - {e.response.text}")
|
51 |
+
return {"error": f"SERP API request failed: {e.response.status_code}"}
|
52 |
+
except httpx.RequestError as e:
|
53 |
+
logger.error(f"SERP API request error: {e}")
|
54 |
+
return {"error": f"SERP API connection error: {e}"}
|
55 |
+
except json.JSONDecodeError as e:
|
56 |
+
logger.error(f"Failed to decode SERP API JSON response: {e}")
|
57 |
+
return {"error": "Failed to parse SERP API response."}
|
58 |
+
except Exception as e:
|
59 |
+
logger.exception("Unexpected error during SERP API call.")
|
60 |
+
return {"error": f"An unexpected error occurred: {e}"}
|
61 |
+
|
62 |
+
# Add similar functions or a class for other external APIs (Weather, Finance etc.)
|
63 |
+
# in external_apis.py, using httpx for async calls.
|