weixin_tools.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. from __future__ import annotations
  2. import json
  3. import logging
  4. from agent.tools import tool, ToolResult
  5. from src.infra.shared.http_client import AsyncHttpClient
  6. from src.infra.shared.common import extract_history_articles
  7. logger = logging.getLogger(__name__)
  8. # url from aigc
  9. base_url = "http://crawler-cn.aiddit.com/crawler/wei_xin"
  10. headers = {"Content-Type": "application/json"}
  11. @tool(description="通过关键词搜索微信文章")
  12. async def weixin_search(keyword: str, page="1") -> dict | None:
  13. """
  14. 微信关键词搜索
  15. 通过关键词搜索微信的文章信息,page 用于控制翻页
  16. Args:
  17. keyword: 搜索关键词
  18. Returns:
  19. ToolResult: 包含以下内容:
  20. - output: 文本格式的搜索结果摘要
  21. - metadata.search_results: 结构化的搜索结果列表
  22. - title: 文章标题
  23. - url: 文章链接
  24. - statistics: 统计数据
  25. - time: 文章发布时间戳(秒)
  26. - metadata.raw_data: 原始 API 返回数据
  27. Note:
  28. - 使用 next_cursor 参数可以获取下一页结果
  29. - 建议从 metadata.search_results 获取结构化数据,而非解析 output 文本
  30. - 返回的 next_cursor 值可用于下一次搜索的 cursor 参数
  31. """
  32. url = "{}/keyword".format(base_url)
  33. payload = json.dumps({"keyword": keyword, "cursor": page})
  34. try:
  35. async with AsyncHttpClient(timeout=120) as http_client:
  36. response = await http_client.post(url=url, headers=headers, data=payload)
  37. except Exception as e:
  38. print(e)
  39. return None
  40. print(json.dumps(response, ensure_ascii=False, indent=4))
  41. return response
  42. @tool(description="通过公众号文章链接获取公众号详情信息")
  43. async def fetch_weixin_account(content_link: str) -> dict | None:
  44. """
  45. 通过公众号文章链接获取公众号的详情信息
  46. Args:
  47. content_link: 公众号文章链接
  48. Returns:
  49. ToolResult: 包含以下内容:
  50. - output: 文本格式的公众号详情摘要
  51. - metadata.account_info: 公众号详情信息
  52. - account_name: 公众号名称
  53. - wx_gh: 公众号ID
  54. - biz_info: 公众号biz信息
  55. - channel_account_id: 公众号账号内部ID
  56. - metadata.raw_data: 原始 API 返回数据
  57. Note:
  58. - 建议从 metadata.account_info 获取结构化数据,而非解析 output 文本
  59. """
  60. url = "{}/account_info".format(base_url)
  61. payload = json.dumps({"content_link": content_link, "is_cache": False})
  62. try:
  63. async with AsyncHttpClient(timeout=120) as http_client:
  64. response = await http_client.post(url=url, headers=headers, data=payload)
  65. except Exception as e:
  66. logger.error(e)
  67. return None
  68. print(json.dumps(response, ensure_ascii=False, indent=4))
  69. return response
  70. @tool(description="通过微信公众号的 wx_gh 获取微信公众号的历史发文列表")
  71. async def fetch_account_article_list(wx_gh: str, index=None, is_cache=True) -> dict | None:
  72. """
  73. 通过公众号的 wx_gh 获取历史发文列表
  74. Args:
  75. wx_gh: 公众号ID
  76. index: 分页索引
  77. is_cache: 是否使用缓存
  78. Returns:
  79. ToolResult: 包含以下内容:
  80. - output: 文本格式历史发文列表摘要
  81. - metadata.next_cursor: 游标,用于下一页查询
  82. - metadata.articles: 历史发文列表
  83. - msg_id: 发布消息ID
  84. - title: 文章标题
  85. - digest: 文章摘要描述
  86. - content_url: 文章链接
  87. - cover_url: 封面链接
  88. - create_time: 文章发布时间戳
  89. - position: 文章位置
  90. - statistics: 统计数据
  91. - view_count: 文章阅读量
  92. - like_count: 文章点赞量
  93. - pay_count: 文章付费量
  94. - zs_count: 文章赞赏量
  95. - metadata.raw_data: 原始 API 返回数据
  96. Note:
  97. - 使用 next_cursor 参数可以获取下一页结果
  98. - 建议从 metadata.history_articles 获取结构化数据,而非解析 output 文本
  99. - metadata.raw_data: 原始 API 返回数据
  100. """
  101. url = "{}/blogger".format(base_url)
  102. payload = json.dumps(
  103. {
  104. "account_id": wx_gh,
  105. "cursor": index,
  106. "token": "1fa4c0ad5c66e43ebd525611f3869f53",
  107. "is_cache": is_cache,
  108. }
  109. )
  110. try:
  111. async with AsyncHttpClient(timeout=120) as http_client:
  112. response = await http_client.post(url=url, headers=headers, data=payload)
  113. except Exception as e:
  114. logger.error(e)
  115. return None
  116. return extract_history_articles(response)
  117. @tool(description="通过公众号文章链接获取文章详情")
  118. async def fetch_article_detail(article_link: str, is_count: bool = False, is_cache: bool = True) -> dict | None:
  119. """
  120. 通过公众号的 文章链接获取文章详情
  121. Args:
  122. article_link: 文章链接
  123. is_count: 是否统计文章阅读量 默认 False
  124. is_cache: 是否使用缓存 默认 True
  125. Returns:
  126. ToolResult: 包含以下内容:
  127. - output: 文本格式文章详情摘要
  128. - metadata.article_info: 文章详情信息
  129. - title: 文章标题
  130. - channel_content_id: 文章内部ID
  131. - content_link: 文章链接
  132. - body_text: 文章正文文本
  133. - mini_program: 文章嵌入小程序信息【若无则是空数组】
  134. - image_url_list: 文章图片列表【若无则是空数组】
  135. - publish_timestamp: 文章发布时间戳【毫秒时间戳】
  136. - metadata.raw_data: 原始 API 返回数据
  137. Note:
  138. - 建议从 metadata.article_info 获取结构化数据,而非解析 output 文本
  139. - metadata.raw_data: 原始 API 返回数据
  140. """
  141. target_url = f"{base_url}/detail"
  142. payload = json.dumps(
  143. {
  144. "content_link": article_link,
  145. "is_count": is_count,
  146. "is_ad": False,
  147. "is_cache": is_cache,
  148. }
  149. )
  150. try:
  151. async with AsyncHttpClient(timeout=10) as http_client:
  152. response = await http_client.post(target_url, headers=headers, data=payload)
  153. except Exception as e:
  154. print(e)
  155. return None
  156. return response
  157. if __name__ == "__main__":
  158. url = "http://mp.weixin.qq.com/s?__biz=MjM5ODI5NTE2MA==&mid=2651871172&idx=1&sn=791630221da3b28fc23949c48c994218&chksm=bc39e9a2a29ea779aef9f6a510f24c3b0addfbc08c86d2d20f8bce0c132fc9b0bed98dc6c8ee&scene=7#rd"
  159. async def run():
  160. response = await fetch_article_detail(url)
  161. import json
  162. print(json.dumps(response, ensure_ascii=False, indent=4))
  163. import asyncio
  164. asyncio.run(run())