【Python+微信】【企业微信开发入坑指北】4. 企业微信接入GPT,只需一个URL,自动获取文章总结

简介: 【Python+微信】【企业微信开发入坑指北】4. 企业微信接入GPT,只需一个URL,自动获取文章总结
  • 大家好,我是同学小张,日常分享AI知识和实战案例
  • 欢迎 点赞 + 关注 👏,持续学习持续干货输出
  • 一起交流💬,一起进步💪。
  • 微信公众号也可搜【同学小张】 🙏

本站文章一览:


经过这么多天的探索,终于到了激动人心的时刻。我们终于可以在企业微信和AI大模型应用方面做点稍微复杂点的功能了。

本文实现的效果如下:在微信中给企业微信发一个URL,它就能自动帮你总结出这个URL背后的网页所讲的内容。

想象一下,你平时在上网的过程中,看到一篇貌似很符合你需求的文章,但是并不能确定是否真的值得读。这时候,丢一个URL给微信,它给你输出总结,通过总结先来概览以下文章内容,再决定是不是要细看。是不是很有意义的一个功能?

其实市面上已经有很多类似的功能,比如Kimi Chat等,都有类似功能。本文是此类功能的一种实现方式,并且与微信联系了起来。

话不多说,开整。

1. 接收用户消息并处理

详细教程链接(如何接收用户消息,如何给用户回复消息等):【Python+微信】【企业微信开发入坑指北】1. 数据链路打通:接收用户消息处理并回复

1.1 主要代码

在之前代码的基础上,我们增加一下以下判断,只要发来的消息中带有 http 或 https 字样,就认为是一个url,就走我们本文的处理:爬取内容,总结内容。

if decrypt_data.get('Content', '').find("http://") != -1 or decrypt_data.get('Content', '').find("https://") != -1:
        response_content = await summary_url(decrypt_data.get('Content', ''))

当然,我也知道这种方式非常地… 不好,很容易误判,但对于目前的我来说够用了。实际工程中可能会考虑需要用户输入特定指令来触发该功能等更严格和标准的方式。

1.2 注意事项

前面我们也说了,企业微信服务只给我我们5s的响应时间,如果5s没返回响应,会触发重试。重试3次。

而对于本文所述功能来说,很容易超过5s。对于该问题的解决方法,前面也有文章讨论过

我这里也简单解决了一下该问题:用一个 Messages存储接收到的消息,当该消息已经在里面的时候,视为重试消息,直接返回一个 “success”。不在里面时,才视为新消息,触发后面的逻辑。这样保证了不会重复处理相同的请求。

Messages = {}
msg_id = decrypt_data.get('MsgId')
if (msg_id in Messages.keys()):
    return "success"
Messages[msg_id] = decrypt_data

然后,在消息处理完有结果之后,通过主动发送消息接口,将结果传给用户。

主动给企业微信发消息的教程参考:【Python+微信】【企业微信开发入坑指北】2. 如何利用企业微信API主动给用户发应用消息

if decrypt_data.get('Content', '').find("http://") != -1 or decrypt_data.get('Content', '').find("https://") != -1:
    response_content = await summary_url(decrypt_data.get('Content', ''))
    weichat_app.send_text(content=response_content)

2. 后台服务处理程序(通用爬虫+总结)

有了上面的与用户交互的通道之后,剩下的就是其背后的主要处理过程了。

用户发一个URL过来,后台服务应该解析该URL,获取网页中的内容,然后进行总结。

2.1 通用爬虫

获取网页中的内容,就是前面我们探讨过的爬虫的内容(【Python实用技能】爬虫升级之路:从专用爬虫到用AI Agent实现通用网络爬虫(适合小白)),为了能满足用户输入的任意URL,我们需要使用进阶版的通用爬虫,也就是利用AI Agent实现通用爬虫。

我们将之前的代码提取出来,稍微修改下作为一个通用爬虫模块来使用。

2.1.1 大模型写爬虫代码

def get_outline(page):
    soup = _get_soup(page.html)
    outline = []
    def process_element(element, depth):
        name = element.name
        if not name:
            return
        if name in ["script", "style"]:
            return
        element_info = {"name": element.name, "depth": depth}
        if name in ["svg"]:
            element_info["text"] = None
            outline.append(element_info)
            return
        element_info["text"] = element.string
        # Check if the element has an "id" attribute
        if "id" in element.attrs:
            element_info["id"] = element["id"]
        if "class" in element.attrs:
            element_info["class"] = element["class"]
        outline.append(element_info)
        for child in element.children:
            process_element(child, depth + 1)
    try:
        for element in soup.body.children:
            process_element(element, 1)
    except:
        logger.error("get outline error")
        outline = []
    return outline
PROMPT_TEMPLATE = """Please complete the web page crawler parse function to achieve the User Requirement. The parse \
function should take a BeautifulSoup object as input, which corresponds to the HTML outline provided in the Context.
``python
from bs4 import BeautifulSoup
# only complete the parse function
def parse(soup: BeautifulSoup):
    ...
    # Return the object that the user wants to retrieve, don't use print
``
## User Requirement
{requirement}
## Context
The outline of html page to scrabe is show like below:
``tree
{outline}
``
"""
class WriteCrawlerCode(Action):
    async def run(self, url, requirement):
        codes = {}
        codes[url] = await self._write_code(url, requirement)
        if codes[url] == None:
            return None
        return "\n".join(f"# {url}\n{code}" for url, code in codes.items()) ## 返回固定格式的url + 相应爬虫代码
    async def _write_code(self, url, query):
        page = await WebBrowserEngine().run(url)
        outline = get_outline(page)
        if len(outline) == 0:
            return None
        outline = "\n".join(
            f"{' '*i['depth']}{'.'.join([i['name'], *i.get('class', [])])}: {i['text'] if i['text'] else ''}"
            for i in outline
        )
        code_rsp = await self._aask(PROMPT_TEMPLATE.format(outline=outline, requirement=query))
        code = CodeParser.parse_code(block="", text=code_rsp)
        return code

这部分代码与之前基本一致,主要改动是其中加了一点错误的处理机制。该部分的输入是URL和用户想从中提取的信息。

2.1.2 自动执行爬虫代码

输入一个URL与其对应的爬虫代码,自动执行程序获取相关网页内容。

class RunCrawlerCode(Action):
    async def run(self, url, codes):
        code, current = codes.rsplit(f"# {url}", maxsplit=1)
        name = uuid4().hex
        module = type(sys)(name)
        exec(current, module.__dict__)
        page = await WebBrowserEngine().run(url)
        data = getattr(module, "parse")(page.soup)
        print(data)
        return str(data)  # 以字符串形式返回

2.1.3 爬虫工程师角色定义

定义一个爬虫工程师的角色,将上面的两个步骤添加进来。

_act函数中,如果执行的是 WriteCrawlerCode 动作,则传入相应的URL和用户需求Requirement。并需要将结果写入memory中,以供后面的动作取用。

后面的动作通过 msg = self.rc.memory.get(k=1)[0] 获取memory的最新结果,然后运行。

from metagpt.roles import Role
class CrawlerEngineer(Role):
    ......
    def __init__(self, **kwargs) -> None:
        super().__init__(**kwargs)
        self.set_actions([WriteCrawlerCode, RunCrawlerCode])
        
    async def _think(self) -> None:
        ......
    async def _act(self) -> Message:
        """Perform an action as determined by the role.
        Returns:
            A message containing the result of the action.
        """
        todo = self.rc.todo
        if type(todo) is WriteCrawlerCode:
            resp = await todo.run(url=self.url, requirement=self.requirement)
            logger.info(resp)
            if (resp == None):
                return None
            self.rc.memory.add(Message(content=resp, role=self.profile))
            return resp
        msg = self.rc.memory.get(k=1)[0]
        resp = await todo.run(url=self.url, codes=msg.content) # 返回必须是字符串
        logger.info(resp)
        return Message(content=resp, role=self.profile) # resp必须是字符串,MetaGPT中限制的
    async def _react(self) -> Message:
        ......

2.1.4 将以上内容封装调用

class CrawlerDataProvider():
    def __init__(self) -> None:
        pass
    
    async def run(self, url, requirement="获取正文中的所有文字内容,如果正文有code,将code也作为文字内容"):
        msg = "start"
        role = CrawlerEngineer(url = url, requirement = requirement)
        logger.info(msg)
        result = await role.run(msg)
        logger.info("\n=========================================\n")
        logger.info(result)
        return result

封装之后,外部只需要引入这个CrawlerDataProvider类,实例化一个对象就可以直接使用了。使用示例如下:

if __name__ == "__main__":
    url="https://mp.weixin.qq.com/s/2m8MrsCxf5boiH4Dzpphrg"
    requirement="获取标题,正文中的所有文字内容,如果正文有code,将code也作为文字内容"
    data_provider = CrawlerDataProvider()
    asyncio.run(data_provider.run(url, requirement))

2.2 文本内容总结

有了网页内容之后,就可以利用大模型对其进行总结。这里就简单总结一下:

PROMPT_TEMPLATE = """简要总结下面文字的内容:
"{text}"
简要总结:"""
class SummaryArticle():
    def __init__(self) -> None:
        pass
    
    def run(self, text):
        prompt = PROMPT_TEMPLATE.format(text = text)
        response_content = openai_wrapper.get_chat_completion(prompt)
        print("response content: ", response_content)
        return response_content

2.3 组合使用示例

async def summary_url(url):
    text_provider = CrawlerDataProvider()
    text = await text_provider.run(url = url)
    summary = SummaryArticle()
    response_content = summary.run(text = text)
    return response_content
if __name__ == "__main__":
    response = asyncio.run(summary_url(url = "https://mp.weixin.qq.com/s/L_gHW-_TIipmcyDcdQpZRA"))
    print(response)

3. 踩坑

(1)自动运行爬虫程序时,可能遇到 BeautifulSoup is not defined 的错误。一般原因是运行环境缺少 bs4 包。执行以下命令安装即可:

pip install bs4

(2)因为我的服务配置特别特别低,运行速度非常慢,所以经常出现网页获取超时等获取不到内容的情况,非常不稳定… 在自己笔记本上没问题。这个暂时无解。

如果觉得本文对你有帮助,麻烦点个赞和关注呗 ~~~


  • 大家好,我是 同学小张,日常分享AI知识和实战案例
  • 欢迎 点赞 + 关注 👏,持续学习持续干货输出
  • 一起交流💬,一起进步💪。
  • 微信公众号也可搜【同学小张】 🙏

本站文章一览:

相关文章
|
5月前
|
存储 数据采集 自然语言处理
Python爬取公众号文章并实现关键词分析
Python爬取公众号文章并实现关键词分析
|
3月前
|
消息中间件 人工智能 Java
抖音微信爆款小游戏大全:免费休闲/竞技/益智/PHP+Java全筏开源开发
本文基于2025年最新行业数据,深入解析抖音/微信爆款小游戏的开发逻辑,重点讲解PHP+Java双引擎架构实战,涵盖技术选型、架构设计、性能优化与开源生态,提供完整开源工具链,助力开发者从理论到落地打造高留存、高并发的小游戏产品。
|
4月前
|
小程序 JavaScript API
uni-halo + 微信小程序开发实录:我的第一个作品诞生记
这篇文章介绍了使用uni-halo框架进行微信小程序开发的过程,包括选择该框架的原因、开发目标以及项目配置和部署的步骤。
202 0
uni-halo + 微信小程序开发实录:我的第一个作品诞生记
|
7月前
|
小程序 前端开发 Android开发
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
1525 29
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
|
6月前
|
监控 数据可视化 数据处理
微信养号脚本,全自动插件,AUTOJS开发版
这是一套自动化微信养号工具,包含主脚本`wechat_auto.js`与配置文件`config.json`。主脚本实现自动浏览朋友圈、随机阅读订阅号文章及搜索指定公众号三大功能,支持自定义滚动次数、阅读时长等参数。代码通过随机化操作间隔模拟真实用户行为,具备完善的错误处理和日志记录功能。配套UI模块提供可视化操作界面,可实时监控任务状态与运行日志,便于调整参数设置。控制器部分扩展了批量数据处理能力,如学生信息的增删改查操作,适用于多场景应用。下载地址:https://www.pan38.com/share.php?code=n6cPZ 提取码:8888(仅供学习参考)。
|
9月前
|
人工智能 自然语言处理 小程序
技术小白如何利用DeepSeek半小时开发微信小程序?
通过通义灵码的“AI程序员”功能,即使没有编程基础也能轻松创建小程序或网页。借助DeepSeek V3和R1满血版模型,用户只需用自然语言描述需求,就能自动生成代码并优化程序。例如,一个文科生仅通过描述需求就成功开发了一款记录日常活动的微信小程序。此外,通义灵码还提供智能问答模式,帮助用户解决开发中的各种问题,极大简化了开发流程,让普通人的开发体验更加顺畅。
2774 11
技术小白如何利用DeepSeek半小时开发微信小程序?
|
8月前
|
小程序 Java 关系型数据库
weixin163基于微信小程序的校园二手交易平台系统设计与开发ssm(文档+源码)_kaic
本文介绍了一款基于微信小程序的校园二手物品交易平台的开发与实现。该平台采用Java语言开发服务端,使用MySQL数据库进行数据存储,前端以微信小程序为载体,支持管理员和学生两种角色操作。管理员可管理用户、商品分类及信息、交易记录等,而学生则能注册登录、发布购买商品、参与交流论坛等。系统设计注重交互性和安全性,通过SSM框架优化开发流程,确保高效稳定运行,满足用户便捷交易的需求,推动校园资源共享与循环利用。
|
8月前
|
小程序 关系型数据库 Java
weixin168“返家乡”高校暑期社会实践微信小程序设计与开发ssm(文档+源码)_kaic
本文探讨高校暑期社会实践微信小程序的开发与应用,旨在通过信息化手段提升活动管理效率。借助微信小程序技术、SSM框架及MySQL数据库,实现信息共享、流程规范和操作便捷。系统涵盖需求分析、可行性研究、设计实现等环节,确保技术可行、操作简便且经济合理。最终,该小程序可优化活动发布、学生信息管理和心得交流等功能,降低管理成本并提高工作效率。
|
9月前
|
小程序 JavaScript 前端开发
微信小程序开发全流程:从注册到上线的完整指南
这篇文章详细记录了微信小程序的完整开发到最终上线的每一个步骤。适合对小程序开发感兴趣的个人开发者或希望了解完整流程的学习者,涵盖了云开发、事件绑定、生命周期管理、组件使用等关键内容。
5832 11
|
10月前
|
人工智能 芯片
D1net阅闻|OpenAI员工疯狂暗示,内部已成功开发ASI?被曝训出GPT-5但雪藏
D1net阅闻|OpenAI员工疯狂暗示,内部已成功开发ASI?被曝训出GPT-5但雪藏

推荐镜像

更多