import gradio as gr import json from typing import Dict, List, Any import requests class SearchUI: def __init__(self): self.api_key = "8af097ae8b587bb0569425058e03e5ef33b4c7b8b1a505053764b62e7e4ab9d6" def parse_google_results(self, results: Dict) -> List[Dict]: """解析Google搜索结果""" parsed = [] # 解析organic_results if 'organic_results' in results: for result in results['organic_results']: parsed.append({ 'title': result.get('title', ''), 'link': result.get('link', ''), 'snippet': result.get('snippet', ''), 'position': result.get('position', 0) }) # 解析answer_box如果存在 if 'answer_box' in results: answer = results['answer_box'] parsed.append({ 'title': '直接回答:', 'link': answer.get('link', ''), 'snippet': answer.get('answer', ''), 'position': 0 }) return parsed def parse_bing_results(self, results: Dict) -> List[Dict]: """解析Bing搜索结果""" parsed = [] if 'organic_results' in results: for result in results['organic_results']: parsed.append({ 'title': result.get('title', ''), 'link': result.get('link', ''), 'snippet': result.get('snippet', ''), 'position': result.get('position', 0) }) return parsed def parse_baidu_results(self, results: Dict) -> List[Dict]: """解析百度搜索结果""" parsed = [] if 'organic_results' in results: for result in results['organic_results']: parsed.append({ 'title': result.get('title', ''), 'link': result.get('link', ''), 'snippet': result.get('snippet', ''), 'position': result.get('position', 0) }) # 解析百度特有的answer_box if 'answer_box' in results: for answer in results['answer_box']: parsed.append({ 'title': '直接回答:', 'link': answer.get('link', ''), 'snippet': f"{answer.get('answer', '')}\n来源: {answer.get('source', '')}", 'position': 0 }) return parsed def format_results(self, results: List[Dict]) -> str: """将解析后的结果格式化为markdown文本""" formatted = "" for result in sorted(results, key=lambda x: x['position']): formatted += f"### {result['title']}\n\n" formatted += f"🔗 [{result['link']}]({result['link']})\n\n" formatted += f"{result['snippet']}\n\n" formatted += "---\n\n" return formatted def search_all_engines(self, query: str) -> tuple: """在所有搜索引擎中执行搜索并返回格式化结果""" try: results = {} for engine in ["google", "bing", "baidu"]: params = { "api_key": self.api_key, "engine": engine, "q": query } # 为Google添加特殊参数 if engine == "google": params.update({ "gl": "cn", "hl": "zh-cn" }) response = requests.get('https://serpapi.com/search', params=params) if response.status_code == 200: results[engine] = response.json() else: return f"{engine}搜索出错: HTTP {response.status_code}", "", "" # 解析各引擎结果 google_parsed = self.parse_google_results(results['google']) google_text = self.format_results(google_parsed) bing_parsed = self.parse_bing_results(results['bing']) bing_text = self.format_results(bing_parsed) baidu_parsed = self.parse_baidu_results(results['baidu']) baidu_text = self.format_results(baidu_parsed) return google_text, bing_text, baidu_text except Exception as e: return f"搜索出错: {str(e)}", f"搜索出错: {str(e)}", f"搜索出错: {str(e)}" def create_ui(): search_ui = SearchUI() # 自定义CSS样式 custom_css = """ .container {padding: 20px;} /* 搜索引擎区域样式 */ .google-container {background: rgba(66, 133, 244, 0.05); border-radius: 15px; padding: 15px;} .bing-container {background: rgba(0, 169, 157, 0.05); border-radius: 15px; padding: 15px;} .baidu-container {background: rgba(45, 97, 255, 0.05); border-radius: 15px; padding: 15px;} /* 结果卡片样式 */ .result-card { background: white; border-radius: 10px; padding: 15px; margin: 10px 0; box-shadow: 0 2px 4px rgba(0,0,0,0.1); transition: all 0.3s ease; } .result-card:hover { transform: translateY(-3px); box-shadow: 0 4px 8px rgba(0,0,0,0.15); } /* 链接样式 */ .result-card a { color: #1a0dab; text-decoration: none; } .result-card a:hover { text-decoration: underline; } /* 分隔线样式 */ .google-container hr {border-color: rgba(66, 133, 244, 0.2);} .bing-container hr {border-color: rgba(0, 169, 157, 0.2);} .baidu-container hr {border-color: rgba(45, 97, 255, 0.2);} """ def format_with_css(results: str, engine: str) -> str: """为结果添加CSS类""" # 将markdown结果分割成单独的卡片 cards = results.split("---") formatted_cards = [] for card in cards: if card.strip(): formatted_cards.append(f'
{card}
') return f'
{"".join(formatted_cards)}
' with gr.Blocks(title="九鑫多搜索引擎聚合搜索", theme=gr.themes.Soft(), css=custom_css) as demo: gr.Markdown("## 🔍 九鑫多搜索引擎聚合搜索") with gr.Row(): query_input = gr.Textbox( label="搜索关键词", placeholder="请输入要搜索的内容...", lines=1 ) search_button = gr.Button("搜索", variant="primary") # 修改加载动画实现 loading_indicator = gr.HTML( """
loading...

正在搜索中...

""", visible=False ) with gr.Row(): with gr.Column(): gr.Markdown("### 🔵 Google 搜索结果") google_output = gr.HTML() with gr.Column(): gr.Markdown("### 🟢 Bing 搜索结果") bing_output = gr.HTML() with gr.Column(): gr.Markdown("### 🔷 百度搜索结果") baidu_output = gr.HTML() def on_search(query): return [ True, # loading indicator visible "", # clear google output "", # clear bing output "" # clear baidu output ] def after_search(query): google, bing, baidu = search_ui.search_all_engines(query) return [ False, # hide loading indicator format_with_css(google, "google"), format_with_css(bing, "bing"), format_with_css(baidu, "baidu") ] search_button.click( fn=on_search, inputs=[query_input], outputs=[loading_indicator, google_output, bing_output, baidu_output], ).then( fn=after_search, inputs=[query_input], outputs=[loading_indicator, google_output, bing_output, baidu_output], show_progress="minimal" ) return demo if __name__ == "__main__": demo = create_ui() demo.launch(share=True, server_name="0.0.0.0", server_port=10083)