Initial commit with translated description
This commit is contained in:
71
SKILL.md
Normal file
71
SKILL.md
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
name: desearch-web-search
|
||||
description: "搜索网页并获取实时SERP样式结果。"
|
||||
metadata: {"clawdbot":{"emoji":"🌐","homepage":"https://desearch.ai","requires":{"env":["DESEARCH_API_KEY"]}}}
|
||||
---
|
||||
|
||||
# Web Search By Desearch
|
||||
|
||||
Real-time web search returning structured SERP-style results with titles, links, and snippets.
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. Get an API key from https://console.desearch.ai
|
||||
2. Set environment variable: `export DESEARCH_API_KEY='your-key-here'`
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Basic web search
|
||||
desearch.py web "quantum computing"
|
||||
|
||||
# Paginated results
|
||||
desearch.py web "quantum computing" --start 10
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--start` | Pagination offset (default: 0). Use to get the next page of results. |
|
||||
|
||||
## Response
|
||||
|
||||
### Example
|
||||
```bash
|
||||
desearch.py web "best sights in Georgia"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"title": "Cool places and fun things to do in Georgia ? : r/solotravel",
|
||||
"snippet": "I was in Georgia earlier this month. My favorite place was Mtirala National Park in Adjara. The mountains and forest were absolutely beautiful ...",
|
||||
"link": "https://www.reddit.com/r/solotravel/comments/py4wls/cool_places_and_fun_things_to_do_in_georgia/",
|
||||
},
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Notes
|
||||
- Returns up to 10 results per page. Use `--start` to paginate.
|
||||
|
||||
### Errors
|
||||
Status 401, Unauthorized (e.g., missing/invalid API key)
|
||||
```json
|
||||
{
|
||||
"detail": "Invalid or missing API key"
|
||||
}
|
||||
```
|
||||
|
||||
Status 402, Payment Required (e.g., balance depleted)
|
||||
```json
|
||||
{
|
||||
"detail": "Insufficient balance, please add funds to your account to continue using the service."
|
||||
}
|
||||
```
|
||||
|
||||
## Resources
|
||||
- [API Reference](https://desearch.ai/docs/api-reference/get-web)
|
||||
- [Desearch Console](https://console.desearch.ai)
|
||||
6
_meta.json
Normal file
6
_meta.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"ownerId": "kn70rkrynh1pbpb1nh8fztsbnx814573",
|
||||
"slug": "desearch-web-search",
|
||||
"version": "1.0.1",
|
||||
"publishedAt": 1771578642605
|
||||
}
|
||||
131
scripts/desearch.py
Normal file
131
scripts/desearch.py
Normal file
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Desearch Web Search CLI - Real-time SERP-style web search.
|
||||
|
||||
Usage:
|
||||
desearch web "<query>" [options]
|
||||
|
||||
Environment:
|
||||
DESEARCH_API_KEY - Required API key from desearch.ai
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from urllib.error import HTTPError, URLError
|
||||
from urllib.parse import urlencode
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
DESEARCH_BASE = "https://api.desearch.ai"
|
||||
|
||||
|
||||
def get_api_key() -> str:
|
||||
key = os.environ.get("DESEARCH_API_KEY")
|
||||
if not key:
|
||||
print("Error: DESEARCH_API_KEY environment variable not set", file=sys.stderr)
|
||||
print("Get your key at https://console.desearch.ai", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
return key
|
||||
|
||||
|
||||
def api_request(
|
||||
method: str, path: str, params: dict = None, body: dict = None
|
||||
) -> dict | str:
|
||||
api_key = get_api_key()
|
||||
url = f"{DESEARCH_BASE}{path}"
|
||||
|
||||
if method == "GET" and params:
|
||||
filtered = {k: v for k, v in params.items() if v is not None}
|
||||
if filtered:
|
||||
url = f"{url}?{urlencode(filtered, doseq=True)}"
|
||||
|
||||
headers = {
|
||||
"Authorization": f"{api_key}",
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": "Desearch-Clawdbot/1.0",
|
||||
}
|
||||
|
||||
data = None
|
||||
if method == "POST" and body:
|
||||
data = json.dumps(body).encode()
|
||||
|
||||
try:
|
||||
req = Request(url, data=data, headers=headers, method=method)
|
||||
with urlopen(req, timeout=60) as response:
|
||||
raw = response.read().decode()
|
||||
try:
|
||||
return json.loads(raw)
|
||||
except json.JSONDecodeError:
|
||||
return raw
|
||||
except HTTPError as e:
|
||||
error_body = e.read().decode() if e.fp else ""
|
||||
try:
|
||||
return json.loads(error_body)
|
||||
except (json.JSONDecodeError, Exception):
|
||||
return {"error": f"HTTP {e.code}: {e.reason}", "details": error_body}
|
||||
except URLError as e:
|
||||
return {"error": f"Connection failed: {e.reason}"}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
def cmd_web(args):
|
||||
params = {
|
||||
"query": args.query,
|
||||
"start": args.start,
|
||||
}
|
||||
return api_request("GET", "/web", params=params)
|
||||
|
||||
|
||||
def format_web_results(data):
|
||||
lines = []
|
||||
if isinstance(data, str):
|
||||
return data
|
||||
if isinstance(data, dict) and "error" in data:
|
||||
return f"Error: {data['error']}"
|
||||
|
||||
results = data.get("organic_results", data.get("results", []))
|
||||
if not isinstance(results, list):
|
||||
results = []
|
||||
|
||||
lines.append("=== Web Results ===")
|
||||
for i, r in enumerate(results[:10], 1):
|
||||
lines.append(f"\n{i}. {r.get('title', 'No title')}")
|
||||
lines.append(f" {r.get('link', r.get('url', ''))}")
|
||||
snippet = r.get("snippet", r.get("description", ""))
|
||||
if snippet:
|
||||
lines.append(f" {snippet[:200]}")
|
||||
|
||||
return "\n".join(lines) if lines else "No results found."
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Desearch Web Search CLI",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=__doc__,
|
||||
)
|
||||
parser.add_argument(
|
||||
"command", choices=["web"], help="Command to execute"
|
||||
)
|
||||
parser.add_argument("query", help="Search query")
|
||||
|
||||
parser.add_argument(
|
||||
"--start",
|
||||
type=int,
|
||||
default=0,
|
||||
help="Pagination offset (default: 0)",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
results = cmd_web(args)
|
||||
|
||||
if isinstance(results, str):
|
||||
print(results)
|
||||
else:
|
||||
print(json.dumps(results, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user