hot_rank_search.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. """
  2. 热榜搜索工具 - 根据排序类型获取今日热榜内容(news分类)
  3. 用于 Agent 执行时自主调取热榜数据。
  4. """
  5. import asyncio
  6. import json
  7. import os
  8. from typing import Any, Dict, List, Optional
  9. import httpx
  10. from agent.tools import tool, ToolResult
  11. # 热榜搜索 API 配置
  12. HOT_RANK_BASE_URL = os.getenv("HOT_RANK_BASE_URL", "http://crawapi.piaoquantv.com")
  13. DEFAULT_TIMEOUT = 30.0
  14. async def _call_hot_rank_api(
  15. sort_type: str = "最热",
  16. cursor: int = 0,
  17. ) -> Optional[List[Dict[str, Any]]]:
  18. """调用热榜搜索 API,返回结果列表。"""
  19. url = f"{HOT_RANK_BASE_URL.rstrip('/')}/crawler/jin_ri_re_bang/content_rank"
  20. payload = {
  21. "sort_type": sort_type,
  22. "category": "news", # 固定分类
  23. "cursor": cursor,
  24. }
  25. try:
  26. async with httpx.AsyncClient(timeout=DEFAULT_TIMEOUT) as client:
  27. resp = await client.post(url, json=payload)
  28. resp.raise_for_status()
  29. data = resp.json()
  30. except httpx.HTTPStatusError as e:
  31. raise RuntimeError(f"API 请求失败: {e.response.status_code} - {e.response.text[:200]}")
  32. except Exception as e:
  33. raise RuntimeError(f"请求异常: {str(e)}")
  34. # 解析响应格式: {'code': 0, 'data': {'data': [{'jump_url': ..., 'rankList': [...]}]}}
  35. if isinstance(data, dict):
  36. # 检查 code 字段
  37. code = data.get("code", 0)
  38. if code != 0:
  39. raise RuntimeError(f"API 返回错误码: {code}")
  40. # 获取 data.data 数组
  41. outer_data = data.get("data", {})
  42. if isinstance(outer_data, dict):
  43. inner_data = outer_data.get("data", [])
  44. else:
  45. inner_data = outer_data if isinstance(outer_data, list) else []
  46. # 提取所有 rankList 中的条目
  47. all_items = []
  48. if isinstance(inner_data, list):
  49. for item in inner_data:
  50. if item['source'] != '百度':
  51. continue
  52. if isinstance(item, dict):
  53. rank_list = item.get("rankList", [])
  54. if isinstance(rank_list, list):
  55. all_items.extend(rank_list)
  56. return all_items if all_items else []
  57. # 兼容直接返回列表的情况
  58. if isinstance(data, list):
  59. return data
  60. return []
  61. if __name__ == '__main__':
  62. try:
  63. res = asyncio.run(_call_hot_rank_api())
  64. print(res)
  65. except Exception as e:
  66. print(f"执行出错: {e}")
  67. @tool(
  68. description="根据排序类型获取今日热榜内容(news分类),用于创作参考。支持按最热或最新排序,可指定分页游标。",
  69. display={
  70. "zh": {
  71. "name": "热榜搜索",
  72. "params": {
  73. "sort_type": "排序类型:最热 或 最新",
  74. "cursor": "分页游标,从0开始",
  75. },
  76. },
  77. },
  78. )
  79. async def hot_rank_search(
  80. sort_type: str = "最热",
  81. cursor: int = 0,
  82. ) -> ToolResult:
  83. """
  84. 根据排序类型获取今日热榜内容(固定news分类)。
  85. Args:
  86. sort_type: 排序类型,"最热" 或 "最新",默认为 "最热"
  87. cursor: 分页游标,从0开始,默认为 0
  88. Returns:
  89. ToolResult: 热榜内容列表
  90. """
  91. # 验证排序类型
  92. if sort_type not in ["最热", "最新"]:
  93. return ToolResult(
  94. title="热榜搜索失败",
  95. output="",
  96. error=f"排序类型必须是 '最热' 或 '最新',当前为: {sort_type}",
  97. )
  98. # 验证游标
  99. if cursor < 0:
  100. return ToolResult(
  101. title="热榜搜索失败",
  102. output="",
  103. error=f"分页游标必须大于等于0,当前为: {cursor}",
  104. )
  105. try:
  106. results = await _call_hot_rank_api(sort_type=sort_type, cursor=cursor)
  107. except RuntimeError as e:
  108. return ToolResult(
  109. title="热榜搜索失败",
  110. output="",
  111. error=str(e),
  112. )
  113. if not results:
  114. return ToolResult(
  115. title="热榜搜索",
  116. output=json.dumps(
  117. {
  118. "message": "未找到热榜内容",
  119. "sort_type": sort_type,
  120. "category": "news",
  121. "cursor": cursor,
  122. },
  123. ensure_ascii=False,
  124. indent=2,
  125. ),
  126. )
  127. output = json.dumps(results, ensure_ascii=False, indent=2)
  128. return ToolResult(
  129. title=f"热榜搜索 - {sort_type} (news)",
  130. output=output,
  131. long_term_memory=f"检索到热榜内容,排序: {sort_type},分类: news,共 {len(results)} 条",
  132. )