Skill: wjs028-coder/double-search (version 1.0.0)

--- name: double-search description: 双搜索功能 (Tavily + Kimi) - 支持并行搜索和结果合并 metadata: openclaw: emoji: "🔍" requires: bins: ["python3"] env: - TAVILY_API_KEY - KIMI_API_KEY primaryEnv: "TAVILY_API_KEY" install: - id: pip kind: pip packages: ["aiohttp", "python-dotenv"] label: "安装Python依赖 (pip)" --- # Double Search Skill 双重搜索功能，同时使用Tavily和Kimi搜索引擎，提供更全面、准确的搜索结果。 ## 功能特性 - ✅ **双引擎并行搜索**：同时使用Tavily和Kimi - ✅ **智能结果合并**：自动合并、去重和排序 - ✅ **异步高效**：基于asyncio的高性能实现 - ✅ **错误容错**：单个搜索失败不影响整体 - ✅ **灵活配置**：支持环境变量和配置文件 ## 快速开始 ### 1. 安装Python依赖 ```bash pip install aiohttp python-dotenv ``` ### 2. 设置环境变量 在`.env`文件中添加： ```bash TAVILY_API_KEY=tvly-xxxxxxxxxxxx KIMI_API_KEY=your_kimi_api_key_here ``` 或者设置系统环境变量： ```bash export TAVILY_API_KEY="tvly-xxxxxxxxxxxx" export KIMI_API_KEY="your_kimi_api_key_here" ``` ### 3. 基本使用 ```python from double_search import DoubleSearcher async def search_example(): searcher = DoubleSearcher() # 执行搜索 results = await searcher.search("人工智能发展趋势") # 打印结果 print(f"搜索结果: {results}") # 查看各个搜索引擎的结果 print(f"Tavily结果: {results.get('tavily', [])}") print(f"Kimi结果: {results.get('kimi', [])}") return results ``` ## API文档 ### DoubleSearcher类 #### 初始化 ```python searcher = DoubleSearcher() ``` #### search方法 ```python async def search( query: str, merge_results: bool = True, limit_per_source: int = 5 ) -> Dict[str, Any] ``` **参数：** - `query` (str): 搜索查询字符串 - `merge_results` (bool): 是否合并结果（默认True） - `limit_per_source` (int): 每个搜索源返回的结果数量（默认5） **返回：** ```json { "query": "搜索内容", "merged_results": [ { "title": "结果标题", "url": "https://example.com", "snippet": "结果摘要", "source": "tavily" } ], "source_breakdown": { "tavily": [...], "kimi": [...] } } ``` ## 高级用法 ### 1. 不合并结果 ```python results = await searcher.search( query="技术趋势", merge_results=False ) # 结果按搜索源分开 print(results['tavily']) print(results['kimi']) ``` ### 2. 限制每个源的结果数量 ```python results = await searcher.search( query="市场分析", limit_per_source=3 ) ``` ### 3. 自定义结果处理 ```python results = await searcher.search("投资策略") # 只获取Tavily的结果 tavily_results = results.get('tavily', []) # 只获取Kimi的结果 kimi_results = results.get('kimi', []) # 获取合并的结果 all_results = results.get('merged_results', []) ``` ## 配置管理 ### 环境变量配置 ```bash # 必需 TAVILY_API_KEY=tvly-xxxxxxxxxxxx # 可选（不设置则只使用Tavily） KIMI_API_KEY=your_kimi_api_key_here ``` ### 配置文件支持 支持`.env`文件： ```bash # .env文件示例 TAVILY_API_KEY=tvly-xxxxxxxxxxxx KIMI_API_KEY=your_kimi_api_key_here ``` ## 错误处理 ```python async def safe_search(query: str): searcher = DoubleSearcher() try: results = await searcher.search(query) if not results['merged_results']: return {"error": "搜索无结果", "query": query} return results except Exception as e: return {"error": f"搜索失败: {str(e)}", "query": query} ``` ## 性能优化 ### 并行搜索效率 - Tavily和Kimi同时搜索，总时间接近较慢的搜索引擎 - 适合需要全面结果的场景 ### 结果缓存 ```python from functools import lru_cache class CachedSearcher(DoubleSearcher): @lru_cache(maxsize=100) async def search(self, query: str, ...): return await super().search(query, ...) ``` ## 使用场景 ### 1. 内容创作 ```python async def research_topic(topic): searcher = DoubleSearcher() results = await searcher.search(topic) # 分析多个来源 insights = analyze_results(results) return insights ``` ### 2. 财经分析 ```python async def financial_analysis(ticker): searcher = DoubleSearcher() query = f"{ticker} 财经分析" results = await searcher.search(query) # 过滤财经相关结果 financial_news = filter_financial_content(results) return financial_news ``` ### 3. 代码搜索 ```python async def code_search(problem): searcher = DoubleSearcher() results = await searcher.search(problem) # 优先获取技术相关结果 technical_results = filter_tech_content(results) return technical_results ``` ## 故障排除 ### 问题1：搜索无结果 ```bash # 检查API keys echo $TAVILY_API_KEY echo $KIMI_API_KEY # 验证API keys有效性 ``` ### 问题2：Python模块未找到 ```bash # 确保在正确的工作目录 cd ~/.openclaw/skills/double-search # 检查Python路径 which python3 ``` ### 问题3：依赖缺失 ```bash # 安装依赖 pip install aiohttp python-dotenv ``` ## 版本信息 - **版本**: 1.0.0 - **Python版本**: 3.8+ - **更新日期**: 2026-03-27 - **兼容性**: OpenClaw skill系统

path: install.sh
content: #!/bin/bash

# Double Search Skill 一键安装和配置脚本

set -e

echo "=========================================="
echo "Double Search Skill 安装脚本"
echo "=========================================="
echo ""

# 颜色定义
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color

# 获取脚本目录
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

echo "📍 当前目录: $SCRIPT_DIR"
echo ""

# 1. 检查Python版本
echo "📦 检查Python版本..."
if ! command -v python3 &> /dev/null; then
    echo -e "${RED}❌ 错误: Python3未安装${NC}"
    echo "请先安装Python 3.8或更高版本"
    exit 1
fi

PYTHON_VERSION=$(python3 --version | awk '{print $2}')
echo -e "${GREEN}✅ Python版本: $PYTHON_VERSION${NC}"
echo ""

# 2. 检查Python依赖
echo "📋 检查Python依赖..."

if python3 -c "import aiohttp" 2>/dev/null; then
    echo -e "${GREEN}✅ aiohttp 已安装${NC}"
else
    echo -e "${YELLOW}⚠️  aiohttp 未安装，正在安装...${NC}"
    pip3 install aiohttp python-dotenv --quiet
    echo -e "${GREEN}✅ aiohttp 安装完成${NC}"
fi

if python3 -c "import dotenv" 2>/dev/null; then
    echo -e "${GREEN}✅ python-dotenv 已安装${NC}"
else
    echo -e "${YELLOW}⚠️  python-dotenv 未安装，正在安装...${NC}"
    pip3 install python-dotenv --quiet
    echo -e "${GREEN}✅ python-dotenv 安装完成${NC}"
fi

echo ""

# 3. 检查API Keys
echo "🔑 检查API Keys配置..."

TAVILY_KEY="${TAVILY_API_KEY:-}"
KIMI_KEY="${KIMI_API_KEY:-}"

if [ -n "$TAVILY_KEY" ]; then
    echo -e "${GREEN}✅ TAVILY_API_KEY 已设置${NC}"
    echo "   Key前缀: ${TAVILY_KEY:0:10}..."
else
    echo -e "${RED}❌ TAVILY_API_KEY 未设置${NC}"
    echo "   请设置TAVILY_API_KEY环境变量或创建.env文件"
fi

if [ -n "$KIMI_KEY" ]; then
    echo -e "${GREEN}✅ KIMI_API_KEY 已设置${NC}"
    echo "   Key前缀: ${KIMI_KEY:0:10}..."
else
    echo -e "${YELLOW}⚠️  KIMI_API_KEY 未设置（可选）${NC}"
    echo "   只使用Tavily搜索"
fi

echo ""

# 4. 创建.env文件（如果不存在）
if [ ! -f "$SCRIPT_DIR/.env" ]; then
    echo "📝 创建.env配置文件..."
    cat > "$SCRIPT_DIR/.env" << EOF
# Double Search Skill 配置文件
# 请在此处填入您的API Keys

# Tavily Search API Key (必需)
# 获取地址: https://app.tavily.com/
TAVILY_API_KEY=

# Kimi Search API Key (可选)
# 获取地址: https://api.moonshot.cn/
KIMI_API_KEY=
EOF
    echo -e "${GREEN}✅ .env文件创建成功${NC}"
    echo -e "${YELLOW}⚠️  请编辑.env文件，填入您的API Keys${NC}"
else
    echo -e "${GREEN}✅ .env文件已存在${NC}"
fi

echo ""

# 5. 测试搜索功能
echo "🧪 测试搜索功能..."
echo ""

python3 "$SCRIPT_DIR/__init__.py"

if [ $? -eq 0 ]; then
    echo ""
    echo "=========================================="
    echo -e "${GREEN}✅ 安装和测试完成！${NC}"
    echo "=========================================="
    echo ""
    echo "💡 使用方法:"
    echo ""
    echo "1. 在Python代码中导入:"
    echo "   from double_search import DoubleSearcher"
    echo ""
    echo "2. 创建搜索器实例:"
    echo "   searcher = DoubleSearcher()"
    echo ""
    echo "3. 执行搜索:"
    echo "   results = await searcher.search('您的搜索查询')"
    echo ""
    echo "📖 详细文档: SKILL.md"
    echo ""
else
    echo ""
    echo "=========================================="
    echo -e "${RED}❌ 测试失败${NC}"
    echo "=========================================="
    echo ""
    echo "💡 解决方案:"
    echo ""
    echo "1. 检查API Keys是否正确设置"
    echo "2. 检查Python依赖是否安装成功"
    echo "3. 查看错误信息并修复"
    echo ""
    exit 1
fi

echo ""
echo "✨ Double Search Skill 已就绪！"
echo ""


path: __init__.py
content: """
Double Search Skill - 双搜索功能实现
支持Tavily和Kimi两个搜索引擎的并行搜索和结果合并
"""

import asyncio
import os
from typing import List, Dict, Any, Optional
from abc import ABC, abstractmethod


class SearchEngine(ABC):
    """搜索引擎抽象基类"""

    @abstractmethod
    async def search(self, query: str, **kwargs) -> List[Dict[str, Any]]:
        """执行搜索"""
        pass


class TavilySearch(SearchEngine):
    """Tavily搜索引擎实现"""

    def __init__(self, [REDACTED_SECRET] = None):
        self.[REDACTED_SECRET] or os.getenv("TAVILY_API_KEY")
        self.engine_name = "tavily"

        if not self.api_key:
            raise ValueError("TAVILY_API_KEY environment variable not set")

    async def search(self, query: str, **kwargs) -> List[Dict[str, Any]]:
        """
        执行Tavily搜索

        Args:
            query: 搜索查询
            **kwargs: 其他参数

        Returns:
            搜索结果列表
        """
        try:
            import aiohttp

            headers = {
                "Authorization": f"Bearer {self.api_key}",
                "Accept": "application/json"
            }

            params = {
                "q": query,
                "max_results": kwargs.get("limit_per_source", 5),
                "format": "json"
            }

            async with aiohttp.ClientSession() as session:
                async with session.get(
                    "https://api.tavily.com/search",
                    headers=headers,
                    params=params
                ) as response:
                    if response.status == 200:
                        data = await response.json()
                        results = []

                        for item in data.get("results", []):
                            results.append({
                                "title": item.get("title", ""),
                                "url": item.get("url", ""),
                                "snippet": item.get("content", ""),
                                "source": self.engine_name
                            })

                        return results
                    else:
                        error_text = await response.text()
                        raise Exception(f"Tavily API error: {response.status} - {error_text}")

        except ImportError:
            # 模拟搜索结果（用于演示）
            await asyncio.sleep(0.1)
            return [
                {
                    "title": f"Tavily结果: {query}",
                    "url": "https://tavily.com/demo",
                    "snippet": "这是Tavily搜索的模拟结果。实际使用时需要安装aiohttp库。",
                    "source": self.engine_name
                }
            ]


class KimiSearch(SearchEngine):
    """Kimi搜索引擎实现"""

    def __init__(self, [REDACTED_SECRET] = None):
        self.[REDACTED_SECRET] or os.getenv("KIMI_API_KEY")
        self.engine_name = "kimi"

        if not self.api_key:
            raise ValueError("KIMI_API_KEY environment variable not set")

    async def search(self, query: str, **kwargs) -> List[Dict[str, Any]]:
        """
        执行Kimi搜索

        Args:
            query: 搜索查询
            **kwargs: 其他参数

        Returns:
            搜索结果列表
        """
        try:
            import aiohttp

            headers = {
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            }

            data = {
                "query": query,
                "max_results": kwargs.get("limit_per_source", 5)
            }

            async with aiohttp.ClientSession() as session:
                async with session.post(
                    "https://api.moonshot.cn/v1/chat/completions",
                    headers=headers,
                    json=data
                ) as response:
                    if response.status == 200:
                        json_data = await response.json()

                        # 解析Kimi API响应
                        results = []
                        for choice in json_data.get("choices", []):
                            message = choice.get("message", {})
                            content = message.get("content", "")

                            # 简化解析（实际需要根据Kimi API返回格式调整）
                            results.append({
                                "title": content[:50] + "..." if len(content) > 50 else content,
                                "url": "https://kimi.com/search",
                                "snippet": content,
                                "source": self.engine_name
                            })

                        return results
                    else:
                        error_text = await response.text()
                        raise Exception(f"Kimi API error: {response.status} - {error_text}")

        except ImportError:
            # 模拟搜索结果（用于演示）
            await asyncio.sleep(0.1)
            return [
                {
                    "title": f"Kimi结果: {query}",
                    "url": "https://kimi.com/demo",
                    "snippet": "这是Kimi搜索的模拟结果。实际使用时需要安装aiohttp库。",
                    "source": self.engine_name
                }
            ]


class MultiSearchManager:
    """多搜索管理器"""

    def __init__(self):
        self.engines: Dict[str, SearchEngine] = {}
        self._load_engines()

    def _load_engines(self):
        """加载可用的搜索引擎"""
        try:
            if os.getenv("TAVILY_API_KEY"):
                self.engines["tavily"] = TavilySearch()
                print(f"✅ Tavily搜索引擎已加载")

            if os.getenv("KIMI_API_KEY"):
                self.engines["kimi"] = KimiSearch()
                print(f"✅ Kimi搜索引擎已加载")

            if not self.engines:
                raise ValueError("没有可用的搜索引擎API keys")

        except Exception as e:
            print(f"⚠️  警告: {e}")
            print(f"💡 提示: 请设置TAVILY_API_KEY和/或KIMI_API_KEY环境变量")

    async def search_all(
        self,
        query: str,
        limit_per_source: int = 5
    ) -> Dict[str, List[Dict[str, Any]]]:
        """
        同时搜索所有配置的搜索引擎

        Args:
            query: 搜索查询
            limit_per_source: 每个搜索引擎的结果数量

        Returns:
            各个搜索引擎的搜索结果
        """
        if not self.engines:
            raise ValueError("没有可用的搜索引擎")

        tasks = {}
        for name, engine in self.engines.items():
            tasks[name] = engine.search(query, limit_per_source=limit_per_source)

        # 并行执行所有搜索
        results = await asyncio.gather(*tasks.values(), return_exceptions=True)

        # 整理结果
        final_results = {}
        for name, result in zip(tasks.keys(), results):
            if isinstance(result, Exception):
                print(f"⚠️  {name}搜索失败: {result}")
                final_results[name] = []
            else:
                final_results[name] = result

        return final_results

    def get_available_engines(self) -> List[str]:
        """获取可用的搜索引擎列表"""
        return list(self.engines.keys())


class DoubleSearcher:
    """双重搜索器 - 主要接口类"""

    def __init__(self):
        self.search_manager = MultiSearchManager()

    async def search(
        self,
        query: str,
        merge_results: bool = True,
        limit_per_source: int = 5
    ) -> Dict[str, Any]:
        """
        执行统一搜索

        Args:
            query: 搜索查询
            merge_results: 是否合并结果（默认True）
            limit_per_source: 每个搜索引擎的结果数量

        Returns:
            搜索结果字典
        """
        print(f"\n🔍 搜索查询: {query}")
        print(f"📊 可用搜索引擎: {', '.join(self.search_manager.get_available_engines())}")

        # 执行搜索
        source_results = await self.search_manager.search_all(
            query,
            limit_per_source=limit_per_source
        )

        # 构建响应
        response = {
            "query": query,
            "source_breakdown": source_results
        }

        # 合并结果（如果需要）
        if merge_results and source_results:
            response["merged_results"] = self._merge_results(source_results)
        elif source_results:
            response["results"] = source_results

        print(f"✅ 搜索完成，共找到 {len(response.get('merged_results', []))} 条结果\n")

        return response

    def _merge_results(self, source_results: Dict[str, List[Dict[str, Any]]]) -> List[Dict[str, Any]]:
        """
        合并来自不同搜索引擎的结果

        Args:
            source_results: 各搜索引擎的结果字典

        Returns:
            合并后的结果列表
        """
        merged = []

        for source, results in source_results.items():
            for result in results:
                # 添加来源标识
                result["source"] = source
                merged.append(result)

        # 按标题排序
        return sorted(merged, key=lambda x: x["title"].lower())


async def main():
    """主函数 - 用于测试"""
    searcher = DoubleSearcher()

    test_query = "人工智能发展趋势"

    print("=" * 60)
    print("Double Search 功能测试")
    print("=" * 60)

    results = await searcher.search(test_query)

    print("\n" + "=" * 60)
    print("搜索结果汇总")
    print("=" * 60)

    # 打印合并的结果
    for i, item in enumerate(results.get('merged_results', [])[:3], 1):
        print(f"\n{i}. [{item['source']}] {item['title']}")
        print(f"   链接: {item['url']}")
        print(f"   摘要: {item['snippet'][:100]}...")

    # 打印各搜索引擎的统计
    print("\n" + "=" * 60)
    print("搜索引擎统计")
    print("=" * 60)

    for source, results in results.get('source_breakdown', {}).items():
        print(f"{source.upper()}: {len(results)} 条结果")


if __name__ == "__main__":
    # 运行测试
    asyncio.run(main())


path: README.md
content: # Double Search Skill

双重搜索功能，支持Tavily和Kimi两个搜索引擎的并行搜索和结果合并。

## 📋 特性

- ✅ **双引擎并行搜索**：同时使用Tavily和Kimi
- ✅ **智能结果合并**：自动合并、去重和排序
- ✅ **异步高效**：基于asyncio的高性能实现
- ✅ **错误容错**：单个搜索失败不影响整体
- ✅ **一键安装**：包含安装脚本和配置向导
- ✅ **无需复杂配置**：支持环境变量和.env文件

## 🚀 快速开始

### 方式1：一键安装（推荐）

```bash
cd ~/.openclaw/skills/double-search
chmod +x install.sh
./install.sh
```

### 方式2：手动安装

```bash
# 1. 安装Python依赖
pip install aiohttp python-dotenv

# 2. 设置环境变量
export TAVILY_API_KEY="tvly-xxxxxxxxxxxx"
export KIMI_API_KEY="your_kimi_api_key_here"

# 3. 测试搜索功能
python3 __init__.py
```

## 📖 使用方法

### 基本用法

```python
from double_search import DoubleSearcher

async def search(query: str):
    searcher = DoubleSearcher()
    results = await searcher.search(query)
    return results
```

### 高级用法

```python
from double_search import DoubleSearcher

async def advanced_search(query: str):
    searcher = DoubleSearcher()

    # 自定义参数
    results = await searcher.search(
        query=query,
        merge_results=True,
        limit_per_source=3
    )

    return results
```

## 📚 API文档

### DoubleSearcher类

| 方法 | 说明 |
|------|------|
| `search(query, merge_results=True, limit_per_source=5)` | 执行搜索 |

### 返回格式

```json
{
  "query": "搜索内容",
  "merged_results": [
    {
      "title": "结果标题",
      "url": "https://example.com",
      "snippet": "结果摘要",
      "source": "tavily"
    }
  ],
  "source_breakdown": {
    "tavily": [...],
    "kimi": [...]
  }
}
```

## 🔧 配置

### 环境变量

```bash
# 必需
TAVILY_API_KEY=tvly-xxxxxxxxxxxx

# 可选（不设置则只使用Tavily）
KIMI_API_KEY=your_kimi_api_key_here
```

### .env文件

```bash
# .env文件示例
TAVILY_API_KEY=tvly-xxxxxxxxxxxx
KIMI_API_KEY=your_kimi_api_key_here
```

## 📝 示例代码

运行示例代码：

```bash
python3 example.py
```

示例包括：
- 基本搜索
- 自定义搜索查询
- 不合并结果
- 过滤特定领域结果
- 市场分析任务
- 比较不同搜索引擎

## 🔍 测试

执行内置测试：

```bash
python3 __init__.py
```

## 🛠️ 故障排除

### 问题：搜索无结果

```bash
# 检查API Keys
echo $TAVILY_API_KEY
echo $KIMI_API_KEY

# 验证API Keys有效性
```

### 问题：Python模块未找到

```bash
# 确保在正确的工作目录
cd ~/.openclaw/skills/double-search

# 检查Python路径
which python3
```

### 问题：依赖缺失

```bash
# 重新安装依赖
pip install -r requirements.txt
```

## 📄 许可证

MIT License

## 🤝 贡献

欢迎提交Issue和Pull Request！

## 📞 支持

如有问题，请查看SKILL.md文档或运行示例代码。

---

**版本**: 1.0.0
**更新日期**: 2026-03-27
**作者**: 028 Team


path: example.py
content: """
Double Search Skill 示例代码
演示如何在机器人中使用双搜索功能
"""

import asyncio
from double_search import DoubleSearcher


async def example_basic_search():
    """示例1：基本搜索"""
    print("=" * 60)
    print("示例1: 基本搜索")
    print("=" * 60)

    searcher = DoubleSearcher()

    results = await searcher.search("人工智能发展趋势")

    return results


async def example_custom_query():
    """示例2：自定义搜索查询"""
    print("\n" + "=" * 60)
    print("示例2: 自定义搜索查询")
    print("=" * 60)

    searcher = DoubleSearcher()

    query = "2024年投资策略分析"
    results = await searcher.search(query)

    return results


async def example_no_merge():
    """示例3：不合并结果"""
    print("\n" + "=" * 60)
    print("示例3: 不合并结果")
    print("=" * 60)

    searcher = DoubleSearcher()

    # 不合并结果，查看每个搜索源的单独结果
    results = await searcher.search(
        query="机器学习算法",
        merge_results=False
    )

    print("\nTavily搜索结果:")
    for item in results.get('tavily', []):
        print(f"  - {item['title']}")

    print("\nKimi搜索结果:")
    for item in results.get('kimi', []):
        print(f"  - {item['title']}")

    return results


async def example_filtered_search():
    """示例4：过滤特定领域结果"""
    print("\n" + "=" * 60)
    print("示例4: 过滤财经领域结果")
    print("=" * 60)

    searcher = DoubleSearcher()

    results = await searcher.search("股票市场分析")

    # 过滤财经相关结果
    financial_results = [
        item for item in results.get('merged_results', [])
        if '财经' in item['snippet'] or '股票' in item['snippet'] or '市场' in item['snippet']
    ]

    print(f"\n找到 {len(financial_results)} 条财经相关结果:")
    for item in financial_results[:3]:
        print(f"  - {item['source']}: {item['title']}")

    return financial_results


async def example_market_analysis():
    """示例5：市场分析任务"""
    print("\n" + "=" * 60)
    print("示例5: 市场分析任务")
    print("=" * 60)

    searcher = DoubleSearcher()

    query = "2024年科技行业投资机会"
    results = await searcher.search(query)

    # 分析结果
    analysis = {
        "query": query,
        "total_results": len(results.get('merged_results', [])),
        "sources": results.get('source_breakdown', {}),
        "key_topics": extract_key_topics(results)
    }

    return analysis


def extract_key_topics(results):
    """从搜索结果中提取关键主题"""
    topics = set()

    for item in results.get('merged_results', []):
        snippet = item['snippet'].lower()
        if '人工智能' in snippet or 'AI' in snippet:
            topics.add('AI/人工智能')
        if '投资' in snippet or '基金' in snippet:
            topics.add('投资')
        if '市场' in snippet or '行情' in snippet:
            topics.add('市场分析')
        if '趋势' in snippet or '发展' in snippet:
            topics.add('趋势')

    return sorted(list(topics))


async def example_comparison():
    """示例6：比较不同搜索引擎的结果"""
    print("\n" + "=" * 60)
    print("示例6: 比较不同搜索引擎")
    print("=" * 60)

    searcher = DoubleSearcher()

    results = await searcher.search("区块链技术发展")

    # 比较不同搜索引擎的结果数量
    tavily_count = len(results.get('tavily', []))
    kimi_count = len(results.get('kimi', []))

    print(f"\n搜索引擎对比:")
    print(f"  Tavily: {tavily_count} 条结果")
    print(f"  Kimi:   {kimi_count} 条结果")
    print(f"  总计:   {tavily_count + kimi_count} 条结果")

    return results


async def main():
    """运行所有示例"""
    print("\n" + "=" * 60)
    print("Double Search Skill - 示例代码")
    print("=" * 60)

    try:
        # 运行示例
        await example_basic_search()
        await example_custom_query()
        await example_no_merge()
        await example_filtered_search()
        await example_market_analysis()
        await example_comparison()

        print("\n" + "=" * 60)
        print("✅ 所有示例运行完成")
        print("=" * 60)

    except Exception as e:
        print(f"\n❌ 错误: {e}")
        import traceback
        traceback.print_exc()


if __name__ == "__main__":
    asyncio.run(main())


path: .env
content: # Double Search Skill 配置文件
# 请在此处填入您的API Keys

# Tavily Search API Key (必需)
# 获取地址: https://app.tavily.com/
TAVILY_API_KEY=

# Kimi Search API Key (可选)
# 获取地址: https://api.moonshot.cn/
KIMI_API_KEY=


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)