我是如何用扣子AI工作流筛选并分析自媒体情报信息的

从开始做自媒体以来,一直有个困惑许久的问题没有解决,那就是搜集我关注的相关领域的对标自媒体一手信息,包括文章、评论、点赞、转发等。一方面,是为了了解我关注的内容,另一方面,也是为了逼迫自己学习更多的内容,从而提高自己的能力。

但是,目前市面上还没有一款产品能够满足我的需求,于是,我尝试自己动手来解决这个问题。我的策略就是通过抓取对标公众号的数据,来获取我关注的内容并存入数据库,然后在通过扣子的AI工作流来处理这些数据,进行一定的总结和分析,从而得到我关注的内容。

1. 抓取对标公众号数据

首先,我需要找到我关注的相关领域的对标公众号,然后通过抓取这些公众号的文章、评论、点赞、转发等数据,来获取我关注的内容。然而,我的方法是可以获取到文章信息的,但是获取不到评论、点赞、转发等数据。如果需要获取这些数据,可能需要rpa控制pc端的微信来实现了,由于我主要使用的是Linux和mac电脑,所以暂时没有实现这个功能。

我的方法是通过公众号后台的网页端来获取对标公众号的数据,然后存入数据库,最后生成API来供我调用。

1.1 选取对标账号列表

我是通过csv文件存储我关注的账号,然后通过脚本来读取这些账号,并获取这些账号的文章信息。起初,我还有使用LangChain的loader来获取,并让LLM来更智能的获取账号,然后再做成langchain的tool智能提取文章内容,但是由于抓取过程需要扫码,所以没招,通过python读取它吧。

20240425182014
20240425182116
20240425182148
20240425182233
20240425182248

读取对标账号后,就到了最关键的获取账号下文章列表的过程。

1.2 获取文章列表

我是通过python的selenium库来实现的,通过selenium来操作网页版的公众号后台,在编辑文章页面,插入链接处,是有个搜索公众号文章的功能的,虽然比较隐蔽,一般也是用来在自己文章中插入别的公众号文章用的,很多人可能都不知道有这个功能。

通过这个功能,我就可以获取到账号下所有文章的标题和链接,并存入数据库,至于文章内容,我们也可以一起通过requests访问并存入数据库,但是,这样的话,后面我们在扣子里面会再次访问一遍,从而使工作流变得特别的慢,所以,我在这里用LangChain对每篇文章做了总结,然后,把总结存入数据库,这样,后面在扣子里面访问的时候,就不用再次访问了。

class Mp_his:
    def __init__(self):
        options = Options()
        # options.add_argument('--headless')
        # options.add_argument('--disable-gpu')
        options.add_argument("--incognito")
        self.driver = webdriver.Chrome(options=options)
        self.vars = {}

    def wait_for_window(self, timeout=2):
        time.sleep(round(timeout / 1000))
        wh_now = self.driver.window_handles
        wh_then = self.vars["window_handles"]
        if len(wh_now) > len(wh_then):
            return set(wh_now).difference(set(wh_then)).pop()
    
    def check_exist(self, link):
        # 检查数据库中是否存在该文章
        conn = sqlite3.connect("mp1.db")
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM mp_articles WHERE link = ?", (link,))
        result = cursor.fetchone()
        conn.close()
        return result
    
    def get_his(self):
        os.chdir(os.path.dirname(os.path.abspath(__file__)))
        self.driver.get("http://mp.weixin.qq.com/")
        self.vars["window_handles"] = self.driver.window_handles
        if self.driver.find_elements(By.CLASS_NAME, "login__type__container__scan__qrcode"):
            # 等待二维码出现
            time.sleep(2)
            qrcode = self.driver.find_element(
                By.CLASS_NAME, "login__type__container__scan__qrcode")
            qrcode.screenshot("./qrcode.png")
        # 等待.new-creation__menu-item:nth-child(2) svg出现
        WebDriverWait(self.driver, 60).until(expected_conditions.presence_of_element_located(
            (By.CSS_SELECTOR, ".new-creation__menu-item:nth-child(2) svg")))
        self.driver.find_element(
            By.CSS_SELECTOR, ".new-creation__menu-item:nth-child(2) svg").click()
        self.vars["win670"] = self.wait_for_window(2000)
        self.driver.switch_to.window(self.vars["win670"])
        self.driver.find_element(By.ID, "js_editor_insertlink").click()
        # 从mp.csv中读取公众号名称
        with open('mp.csv', 'r', encoding='utf-8') as f:
            reader = csv.reader(f)
            for row in reader:
                self.driver.find_element(
                    By.XPATH, "//button[contains(.,\'选择其他公众号\')]").click()
                # 输入公众号名称
                self.driver.find_element(
                    By.CSS_SELECTOR, ".weui-desktop-search__wrp .weui-desktop-form__input").send_keys(row[0])
                self.driver.find_element(
                    By.CSS_SELECTOR, ".weui-desktop-search__wrp .weui-desktop-form__input").send_keys(Keys.ENTER)
                time.sleep(1)
                # 选择第一个公众号.inner_link_account_item的第一个
                WebDriverWait(self.driver, 60).until(expected_conditions.presence_of_element_located(
                    (By.CSS_SELECTOR, ".inner_link_account_item:nth-child(1)")
                ))
                self.driver.find_element(
                    By.CSS_SELECTOR, ".inner_link_account_item:nth-child(1)").click()
                # 循环class 为 .inner_link_article_item的 label 标签
                for i in range(1, 10):
                    WebDriverWait(self.driver, 60).until(expected_conditions.presence_of_element_located(
                        (By.CSS_SELECTOR, f".inner_link_article_item:nth-child({i})")))
                    label = self.driver.find_element(
                        By.CSS_SELECTOR, f".inner_link_article_item:nth-child({i})")
                    author = row[0]
                    title = label.find_element(
                        By.CSS_SELECTOR, "div span:nth-child(2)").text
                    publish_date_str = label.find_element(
                        By.CSS_SELECTOR, ".inner_link_article_date").text
                    publish_date = datetime.strptime(
                        publish_date_str, "%Y-%m-%d")
                    link = label.find_element(
                        By.CSS_SELECTOR, "a").get_attribute("href")
                    # 当发布时间小于昨天,结束循环
                    if publish_date < datetime.now() - timedelta(days=7):
                        print("发布时间小于一周,结束循环")
                        break
                    # 数据库里面有这篇文章,结束循环
                    if self.check_exist(link):
                        break
                    
                    summary = ""
                    # 加载html并获取概述
                    if os.environ['SUMMARY_FLAG'] == 'True':
                        loader = AsyncHtmlLoader([link])
                        doc = loader.load()
                        h2t = Html2TextTransformer()
                        docs_transformed = h2t.transform_documents(doc)
                        text_splitter = RecursiveCharacterTextSplitter()
                        texts = text_splitter.split_documents(docs_transformed)
                        prompt_template = """写下一段文字的摘要:
"{text}"
摘要内容:"""
                        prompt = PromptTemplate.from_template(prompt_template)
                        llm_chain = LLMChain(llm=QianfanChatEndpoint(temperature=0.1), prompt=prompt)
                        stuff_chain = StuffDocumentsChain(llm_chain=llm_chain, document_variable_name="text")
                        summary = stuff_chain.invoke(texts)["output_text"]

                    # 写入mysql数据库
                    import mysql.connector
                    
                    mydb = mysql.connector.connect(
                        host="YOUR_HOST",
                        user="YOURUSER",
                        password="YOURPASS",
                        database="YOURDB"
                    )
                    mycursor = mydb.cursor()
                    mycursor.execute(
                        "INSERT INTO mp_articles (title, author, publish_date, link, summary) VALUES (%s, %s, %s, %s, %s)", (title, author, publish_date, link, summary))
                    mydb.commit()

                    print(f"{title} 写入成功")

这个代码使用了Selenium库来控制浏览器,然后通过XPath选择器来定位元素,输入内容,点击按钮,等待页面加载,使用BeautifulSoup库来解析HTML,使用OpenAI的API来生成摘要,最后写入数据库。这里我推荐大家一个免费的mysql数据库,sqlpub.com, 注册后,可以免费使用,感兴趣的可以去试试,我就是用的这个。

这段代码执行的时候会打开浏览器,并弹出二维码,需要手动扫码,然后,会自动化操作到底。至此,抓取数据就已经完成。

2. 生成API

我使用的是fastapi,这样可以跟LangServe保持一致,我是为将来继承进我的AI小助手做好准备。不熟悉fastapi的小伙伴需要自行学习一下基础的语法,或者使用别的web框架,比如flask/django,都可以。

定义路由:

@app.get("/get_articles")
def get_articles():
    articles = get_mp_articles()
    return articles

获取文章列表:

def get_mp_articles():
    # 连接到 MySQL 数据库
    connection = pymysql.connect(
        host="YOURHOST",
        user="YOURUSER",
        password="YOURPASS",
        database="YOURDB",
    )
    db = connection
    # 查询数据库
    cursor = db.cursor(pymysql.cursors.DictCursor)
    cursor.execute("SELECT title,summary,author,link FROM mp_articles WHERE publish_date >= DATE_SUB(CURDATE(), INTERVAL 2 DAY)")
    articles = cursor.fetchall()
    result = {"articles": articles}
    return result

我只获取最近2天的文章,你可以根据你的需求修改查询条件。

这样,API接口就开发出来了,最后就需要再扣子上对接了。

3. 对接扣子

3.1 创建插件

进入扣子的后台,在个人空间,点击插件标签,点击创建插件,填写相关信息,选择类型为基于已有服务,填写接口地址为刚才开发的接口地址,其他依据提示填写即可。

20240425223157

创建成功后,再点击创建工具,同样依据提示填写相关信息即可,输入输出的字段要填写完整,最后要进行调试一下才能应用。

20240425223547

3.2 创建工作流

回到个人空间,点击工作流标签,点击创建工作流,填写相关信息,进入工作流的编排页面,选择刚才创建的插件,选择刚才创建的工具,点击添加。按照如图所示的流程进行编排,这样就可以让AI来进行筛选,得到最符合你要求的目标文章了,我写的提示词比较简单,大家可以进一步的优化一下提示词,这个很重要,但是我感觉者就可以满足我的要求了,所以我就直接使用了。

20240425224513

最后,同样要进行调试,调试通过后才能提交。

3.3 创建bot

回到个人空间,点击bot标签,点击创建bot,填写基本信息。

20240425223843

进入编辑页面,整体的编辑内容如下:

20240425224839

提示词可以点那个优化,大模型给优化的效果还是可以的。工作流一定要记得选择刚才创建的工作流,插件,我加了LinkReaderPlugin,方便大模型阅读文章。

3.4 测试bot

测试bot,输入:按照要求获取情报

20240425225158

怎么样?最后的结果还可以吧?发现问题了吗?我要的日期呢?我经过了反复调试都没有给我输出来文章的发表日期,可是,我的数据里明明有这个数据,为什么没有输出来呢?有懂行的小伙伴可以给我解释一下吗?

4. 总结

通过这个案例,我实现了通过AI来筛选自媒体文章的功能,并且通过扣子来完成这个功能。整体下来,还是比较顺畅的,扣子实现了很多原来需要LangChain来完成的功能,它通过可视化的界面来帮助用户完成工作流,大大的简化了开发过程。类似的还有百度的appbuilder、dify、fastGPT等等,这些工具都可以帮助用户快速开发出自己的应用。就像在AI生图用到的comfyUI一样,这种图形化的工作流模式,或许就是AI开发领域的Windows,可以改变人们的开发习惯。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/575697.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mysql中join内外连接查询例子

文章目录 join关键字概要举例using 与 on 区别 join关键字 在MySQL中&#xff0c;JOIN 是一种用于将两个或多个表中的行联合起来的操作。 连接&#xff08;join&#xff09;就是将一张表中的行按照某个条件&#xff08;连接条件&#xff09;与另一张表中的行连接起来形成一个新…

一个排查了一天的BUG,你在摸鱼吧!

站会 在一次日常站会上&#xff0c;组员们轮流分享昨天的工作进展。一个组员提到&#xff1a;“昨天我整天都在排查一个BUG&#xff0c;今天还得继续。” 出于好奇&#xff0c;我问&#xff1a;“是什么BUG让你排查了这么久还没解决呢&#xff1f;” 他解释说&#xff1a;“…

Compose和Android View相互使用

文章目录 Compose和Android View相互使用在Compose中使用View概述简单控件复杂控件嵌入XML布局 在View中使用Compose概述在Activity中使用Compose在Fragment中使用Compose布局使用多个ComposeView 在布局中使用Compose 组合使用 Compose和Android View相互使用 在Compose中使用…

智慧旅游引领旅游行业创新发展:借助智能科技的力量,推动旅游服务的个性化、精准化,提升游客的满意度和忠诚度

随着信息技术的迅猛发展和广泛应用&#xff0c;智慧旅游已成为旅游行业创新发展的重要引擎。智慧旅游借助智能科技的力量&#xff0c;推动旅游服务的个性化、精准化&#xff0c;不仅提升了游客的满意度和忠诚度&#xff0c;也为旅游行业的可持续发展注入了新的活力。本文将从智…

4月25日 C++day4

#include <iostream> using namespace std;class Person {const string name;int age;char sex; public:Person():name("lisi"){cout << "Person无参构造" << endl;}Person(string name,int age,char sex):name(name),age(age),sex(sex)…

【RAG 论文】Chain-of-Note:为 RAG 引入 CoT 让模型生成阅读笔记来提高面对噪音文档和未知场景的鲁棒性

论文&#xff1a;Chain-of-Note: Enhancing Robustness in Retrieval-Augmented Language Models ⭐⭐⭐ Tencent AI Lab, arXiv:2311.09210 文章目录 一、论文速读二、实现的细节2.1 Note Design2.2 Data Collection2.3 Model Training 三、实验结果3.1 QA Performance3.2 对 …

使用新版ESLint,搭配Prettier使用的配置方式

概述 ESLint重大更新(9.0.0版本)后,将不再支持非扁平化配置文件,并且移除了与Prettier冲突的规则,也就是说与Prettier搭配使用,不再需要使用插件“eslint-config-prettier”来处理冲突问题。 注:使用新版的前提条件是Node.js版本必须是18.18.0、20.9.0,或者是>=21.1…

014、Python+fastapi,第一个后台管理项目走向第14步:建立python+fastapi项目,创建common通用模块

一、说明 通用模块主要是完成文件的上传下载&#xff0c;抄吧&#xff0c;要不然怎么叫通用模块呢&#xff1f; 我把RuoYi-Vue3-FastAPI中的验证码模块放在这里了&#xff0c;我觉得验证也比较通用吧&#xff0c; 二、添加common通用模块 1、通用模块没有数据表&#xff0c…

涨跌失据了?现货白银市场的波动如何捕捉

现货白银市场近期出现了强劲的上涨&#xff0c;但近两个交易日&#xff0c;却出现了令人感觉诧异的大跌。很多刚入场打算买入做多的朋友&#xff0c;面对这两天这么强的跌势都感觉无所适从。到底现货白银市场的波动如何才能捕捉呢&#xff1f;下面我们就来讨论一下这个问题。 用…

阿里云物联网平台 | 透传与ICA标准数据格式(Alink JSON)| 定值SDK非动态注册与动态注册 | SOC+4G模组移植方案

文章目录 一、透传与ICA标准数据格式&#xff08;Alink JSON&#xff09;二、定值SDK选非动态注册还是动态注册三、SOC4G模组移植方案 一、透传与ICA标准数据格式&#xff08;Alink JSON&#xff09; 透传和ICA标准数据格式&#xff08;Alink JSON&#xff09;是物联网设备与阿…

DevOps(十二)Jenkins实战之Web发布到远程服务器

前面两篇博文介绍了怎么将django开发的web应用推送到gitlab源码仓库&#xff0c;然后jenkins服务器从gitlab仓库拉下来&#xff0c;布署到jenkins服务器上&#xff0c;并用supervisor进行进程管理&#xff0c;保证web应用一直能正常运行&#xff0c;今天我们继续优化&#xff0…

数据结构:初识集合框架

目录 1. 什么是集合框架2. 集合框架的重要性3. 背后所涉及的数据结构以及算法3.1 什么是数据结构3.2 容器背后对应的数据结构3.3 相关java知识3.4 什么是算法 1. 什么是集合框架 官方教程 Java 集合框架Java Collection Framework &#xff0c;又被称为容器和其实现类classes …

记一次JSON.toJSONString()转换时非属性方法空指针异常排查及toJSONString保留null值属性

记一次JSON.toJSONString()转换时非属性方法空指针异常排查及toJSONString保留null值属性 异常详情 有一个类&#xff0c;里面有两个属性和一个类似工具的getRealName()方法如下&#xff1a; getRealName()方法就是获取这个人的真实名字&#xff0c;如果获取不到就以name返回…

janus模块介绍-SIP Gateway

模块启动 默认的SIP GateWay也是https协议&#xff0c;端口为8088或者8089 如果需要在自己搭建的测试服务上测试SIP GateWay模块&#xff0c;则也需要修改为wss 具体改动如下: 找到/opt/janus/share/janus/demos/siptest.js var server "wss://" window.location…

Python与数据库连接

新建表boss create table 创建表 Code import pymysqlcon pymysql.connect(hostlocalhost,\userroot,\password,\port3306,\dbbusiness) cursorcon.cursor() cursor.execute(create table if not exists boss(id int auto_increment primary key,name varchar(20)not null…

打包的意义 作用等前端概念集合 webpack基础配置等

基础网页是什么&#xff1f; 在学校最基础的三剑客 原生JS CSS H5就可以开发静态网页了 对于浏览器而言也能识别这些基础的文件和语法&#xff0c;真正的所见即所得&#xff0c;非常直接。 为什么要使用框架库&#xff1f; 对于常用的前端框架而言&#xff0c;无论是Vue Rea…

什么样的内外网文档摆渡,可以实现安全高效传输?

内外网文档摆渡通常指的是在内网&#xff08;公司或组织的内部网络&#xff09;和外网&#xff08;如互联网&#xff09;之间安全地传输文件的过程。这个过程需要特别注意安全性&#xff0c;因为内网往往包含敏感数据&#xff0c;直接连接内网和外网可能会带来安全风险。因此会…

为什么深度学习模型在 GPU 上运行得更快:CUDA 编程简介

如今,当我们谈论深度学习时,通常会将其实现与利用 GPU 来提高性能联系起来。 GPU(图形处理单元)最初设计用于加速图像、2D 和 3D 图形的渲染。然而,由于它们能够执行许多并行操作,因此它们的实用性超出了深度学习等应用程序。 GPU 在深度学习模型中的使用始于 2000 年代…

保姆级银河麒麟V10高级服务器离线安装mysql5.7数据库

离线在银河麒麟高级操作系统v10安装mysql5.7 下载mysql5.7 MySQL :: Download MySQL Community Server (Archived Versions) 2、把下载好的包上传到服务器 3、解压 [root1-0001 ~]# cd /data/mysql[root1-0001 mysql]# tar -zxvf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz…

Beego框架学习:深入指南

文章目录 Beego框架学习&#xff1a;深入指南安装与设置创建控制器自定义路由使用中间件使用模板引擎使用ORM Beego框架学习&#xff1a;深入指南 Beego是一个快速开发Go语言应用的开源框架&#xff0c;它基于MVC模式设计&#xff0c;提供了一系列的工具和库&#xff0c;使得开…