news 2026/4/18 8:55:34

NewsAPI、Google Search

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
NewsAPI、Google Search

day39: 外部API封装(NewsAPI、Google Search)

外部API封装(NewsAPI、Google Search)

定义:

1. 概念

把外部 API 封装成你项目里的一个“标准能力模块”,通常要做到:

  1. 统一接口(Interface)
例如所有接口都实现:search(query, **kwargs) -> List[SearchItem]
  1. 配置外置(Config)
API_KEY / BASE_URL / 超时 / 重试 / 限流 / 代理 走环境变量或配置文件,不写死
  1. 错误处理(Resilience)
  • 超时、网络错误

  • 401/403(key/权限)

  • 429(限流)

    • 5xx(对端故障)
      • 做好:重试、退避、降级(fallback)
  1. 结果标准化(Normalization)
不同供应商字段不同:统一成你自己的 SearchResult(title, url, snippet, source, published_at) 结构
  1. 可观测(Observability)
打日志:请求耗时、命中数、失败原因、配额信息(若对端给 header)
  1. 成本控制(Cost & Rate limit)
1. 缓存(相同 query 一段时间内不重复请求) 2. 截断(限制返回条数) 3. 只在需要时调用(Router/Agent decision)

2. NewsAPI 与 Google Search 各适合做什么?

NewsAPI(新闻聚合/检索)

官方文档

典型用法是用 /v2/everything 做关键词检索,支持 q、language、sortBy、from/to、分页等。

注意:NewsAPI 的 Developer 计划通常仅允许开发/测试环境使用,生产要换付费计划(条款要注意)。

Google Search(网页搜索)

官方文档
官方路线一般是 Programmable Search Engine(原 CSE)+ Custom Search JSON API:你需要先创建 Search Engine,然后用 cx(search engine id)+ API key 调接口。

工程上很多人也会用第三方 SERP API(如 Serper/SerpApi)来省去一些麻烦,但是否合规、成本与稳定性要你自己评估。


3. Demo:封装两个外部 API → 变成 Agent 的 Tools

3.1 安装依赖
pip install -U httpx pydantic langgraph langchain-openai langchain-core
3.2 配置环境变量(.env)
# LLMOPENAI_API_KEY=sk-xxx OPENAI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 OPENAI_MODEL=qwen-plus-latest# NewsAPINEWSAPI_KEY=your_newsapi_key# Google Custom Search JSON APIGOOGLE_API_KEY=your_google_api_key GOOGLE_CSE_CX=your_cx
3.3 代码:external_api_tools_demo.py
importosimporttimefromtypingimportList,Optional,Dict,AnyfrompydanticimportBaseModelimporthttpxfromlangchain_core.toolsimportToolfromlangchain_openaiimportChatOpenAIfromlanggraph.prebuiltimportcreate_react_agent# --------- 1) 统一数据结构(标准化输出)---------classSearchItem(BaseModel):title:strurl:strsnippet:str=""source:str=""published_at:str=""# --------- 2) 通用 HTTP 客户端:超时 + 重试 + 退避 ---------classResilientHttp:def__init__(self,timeout_s:float=15.0,max_retries:int=3):self.timeout_s=timeout_s self.max_retries=max_retries self.client=httpx.Client(timeout=timeout_s)defget(self,url:str,params:Dict[str,Any],headers:Optional[Dict[str,str]]=None)->httpx.Response:last_exc=Noneforiinrange(self.max_retries):try:r=self.client.get(url,params=params,headers=headers)# 429/5xx 做退避重试ifr.status_codein(429,500,502,503,504)andi<self.max_retries-1:time.sleep(0.8*(2**i))continuer.raise_for_status()returnrexceptExceptionase:last_exc=eifi<self.max_retries-1:time.sleep(0.8*(2**i))else:raiselast_exc# --------- 3) NewsAPI 封装 ---------classNewsAPIClient:def__init__(self,api_key:str,base_url:str="https://newsapi.org"):self.api_key=api_key self.base_url=base_url.rstrip("/")self.http=ResilientHttp()defsearch_everything(self,q:str,language:str="zh",page_size:int=5,sort_by:str="publishedAt")->List[SearchItem]:url=f"{self.base_url}/v2/everything"params={"q":q,"language":language,"pageSize":page_size,"sortBy":sort_by,"apiKey":self.api_key,}data=self.http.get(url,params=params).json()items=[]foraindata.get("articles",[])[:page_size]:items.append(SearchItem(title=a.get("title",""),url=a.get("url",""),snippet=a.get("description","")or"",source=(a.get("source")or{}).get("name","")or"",published_at=a.get("publishedAt","")or"",))returnitems# --------- 4) Google Custom Search JSON API 封装 ---------classGoogleCSEClient:def__init__(self,api_key:str,cx:str,base_url:str="https://www.googleapis.com/customsearch/v1"):self.api_key=api_key self.cx=cx self.base_url=base_url self.http=ResilientHttp()defsearch(self,q:str,num:int=5,lr:Optional[str]=None)->List[SearchItem]:params={"key":self.api_key,"cx":self.cx,"q":q,"num":min(max(num,1),10),}iflr:params["lr"]=lr# 例如 lr="lang_zh-CN"(按需)data=self.http.get(self.base_url,params=params).json()items=[]foritindata.get("items",[])[:num]:items.append(SearchItem(title=it.get("title",""),url=it.get("link",""),snippet=it.get("snippet","")or"",source="GoogleCSE",published_at="",))returnitemsdefformat_items(items:List[SearchItem])->str:ifnotitems:return"未找到结果。"lines=[]fori,xinenumerate(items,1):lines.append(f"{i}.{x.title}\n -{x.url}\n -{x.snippet}\n - source={x.source}time={x.published_at}".strip())return"\n".join(lines)# --------- 5) 把外部 API 变成 Agent Tools ---------defmain():# LLM(DashScope OpenAI compatible)llm=ChatOpenAI(model=os.getenv("OPENAI_MODEL","qwen-plus-latest"),api_key=os.getenv("OPENAI_API_KEY"),base_url=os.getenv("OPENAI_BASE_URL"),temperature=0.2,)news_key=os.getenv("NEWSAPI_KEY","")google_key=os.getenv("GOOGLE_API_KEY","")google_cx=os.getenv("GOOGLE_CSE_CX","")news_client=NewsAPIClient(news_key)ifnews_keyelseNonegoogle_client=GoogleCSEClient(google_key,google_cx)if(google_keyandgoogle_cx)elseNonedefnews_search_tool(query:str)->str:ifnotnews_client:return"NEWSAPI_KEY 未配置。"items=news_client.search_everything(query,language="zh",page_size=5,sort_by="publishedAt")returnformat_items(items)defweb_search_tool(query:str)->str:ifnotgoogle_client:return"GOOGLE_API_KEY / GOOGLE_CSE_CX 未配置。"items=google_client.search(query,num=5)returnformat_items(items)tools=[Tool(name="NewsSearch",func=news_search_tool,description="搜索新闻(NewsAPI)并返回标题/链接/摘要"),Tool(name="WebSearch",func=web_search_tool,description="搜索网页(Google Custom Search JSON API)并返回标题/链接/摘要"),]agent=create_react_agent(llm,tools)question="帮我找一下最近关于“AI Agent LangGraph GraphRAG”的新闻和网页资料,各给5条,并用中文总结要点。"result=agent.invoke({"messages":[("user",question)]})print(result["messages"][-1].content)if__name__=="__main__":main()
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/9 16:24:10

2026年私有化部署企业微信SCRM大概要花多少钱?性价比高吗?

一、背景&#xff1a;为什么私有化部署成2026年企业刚需&#xff1f;企业数据安全合规压力正以肉眼可见的速度攀升。最新行业调研显示&#xff0c;超70%企业因成本模糊而在私有化SCRM部署决策上滞后——这背后&#xff0c;是《数据安全法》《个人信息保护法》等政策对企业数据自…

作者头像 李华
网站建设 2026/4/18 8:30:46

20251226_174446_我的RAG开源项目300+star了,十分适合新手入门(日志

三个月前&#xff0c;我在 Github 上开源的一个 RAG 练手项目&#xff0c;目前已经有了 327 个 star&#xff0c;总共解决了 22 个 issues。结合过去几个月的项目实践&#xff0c;我重新对项目做了轻量化重构&#xff0c;降低资源消耗与部署门槛。项目地址&#xff1a;https://…

作者头像 李华
网站建设 2026/4/18 7:53:24

2025年,户外安防的终极形态是否是“零布线+零维护”?“黑夜如白昼”竟是营销话术?户外安防摄像头看着一篇就够了

面对参数复杂的户外摄像头&#xff0c;挑选时往往令人困惑。其实&#xff0c;决定日常90%体验的关键并非参数堆砌&#xff0c;而是回归安防本质&#xff1a;**“看得清、装得易、用得省心”**。抓住以下三个核心维度&#xff0c;即可轻松做出选择。**一、全时清晰画质&#xff…

作者头像 李华
网站建设 2026/4/18 8:39:17

开题报告反复被打回?虎贲等考 AI:1 次过审的智能破局方案

毕业论文的第一道 “拦路虎”&#xff0c;非开题报告莫属。选题缺乏创新被否定、研究框架逻辑混乱、文献综述流于表面、研究方法不匹配…… 无数学生陷入 “修改 - 驳回 - 再修改” 的循环&#xff0c;耗时耗力还打击信心。虎贲等考 AI&#xff08;官网&#xff1a;https://www…

作者头像 李华
网站建设 2026/3/21 14:49:48

GraniStudio:两轴圆弧插补例程

1.文件运行 导入工程 双击运行桌面GraniStudio.exe。 通过引导界面导入两轴圆弧插补例程&#xff0c;点击导入按钮。 打开两轴圆弧插补例程所在路径&#xff0c;选中两轴圆弧插补.gsp文件&#xff0c;点击打开&#xff0c;完成导入。 2.功能说明 实现轴1与轴2同时按照负向找原…

作者头像 李华