公众号:dify实验室

基于LLMOps平台-Dify的一站式学习平台。包含不限于:Dify工作流案例、DSL文件分享、模型接入、Dify交流讨论等各类资源分享。

大家好,我是dify实验室的超人阿亚。

今天,我们要挑战一个几乎让每个产品经理、市场分析师甚至创业者都“闻风丧胆”的任务——竞品分析。传统的方式不仅耗时耗力,而且信息零散,效率极低。我就在想,能不能让AI来帮我们干这件苦差事?

于是,这个实验诞生了:我们要打造一个AI助手,你只需要丢给它一个竞品名称,它就能自动上网搜集信息,并生成一份结构化的分析报告初稿。听起来很酷?让我们开始吧!

【核心1:踩坑与弯路】—— 我天真了

一开始,我以为这会很简单。Dify 提供了强大的工作流(Workflow)和内置的 Google Search 工具,我的初步构想是:

“一步到位法” (已失败)
用户输入 -> Google Search 找官网 -> Dify的HTTP节点直接访问官网 -> LLM分析 -> 输出报告。

结果呢?现实给了我一记响亮的耳光。几乎所有稍微正规一点的网站都部署了反爬虫机制(比如Cloudflare),我用HTTP节点发出的请求,就像一个没带通行证的游客,被无情地挡在了门外,返回的都是些无意义的错误代码或加载页面。

这个坑告诉我们: Dify 的代码执行节点有安全沙箱,无法执行网络请求等I/O操作;而直接用HTTP节点去“裸奔”访问,成功率极低。这是从“玩具”到“工具”必须迈过的第一道坎。

【核心2:顿悟与新方案】—— 专业的事交给专业的“特工”

在碰壁之后,我意识到,必须将“信息获取”这个专业任务外包出去。Dify 应该扮演“总指挥”的角色,负责编排整个流程;而网页抓取,需要一个能模拟真实浏览器、应对反爬虫的“前线特工”

这个“特工”,就是我们即将用 Python 和 Docker 构建的一个独立的网页抓取微服务。它接收 Dify 指挥部发来的 URL,然后将“情报”(网页纯文本)传回。

于是,我们清晰的技术架构诞生了:

graph TD
    subgraph "用户端 (User)"
        A[用户输入竞品名称]
    end

    subgraph "Dify 平台 (总指挥)"
        B(开始节点)
        C(工具: Google Search)
        D(代码执行: 提取URL)
        E(HTTP请求: 调用特工)
        F(LLM分析: 整合情报)
        G(直接回复)
    end

    subgraph "外部服务 (前线特工)"
        H[网页抓取服务 (Python API)]
    end

    A --> B
    B -- 竞品名称 --> C
    C -- 搜索结果 --> D
    D -- 官网URL --> E
    E -- 请求抓取URL --> H
    H -- 返回网页纯文本 --> E
    C -- 搜索结果摘要 --> F
    E -- 网页纯文本 --> F
    F -- 结构化分析报告 --> G
    G --> A
    

这个架构完美地实现了“解耦”,让每个组件各司其职,既保证了 Dify 工作流的稳定,又解决了最关键的技术难题。

【核心3:实战步骤】—— 保姆级“抄作业”指南

光说不练假把式,我们来动手实现!

Step 1: 搭建“前线特工”(网页抓取API)

这个服务的目标很纯粹:给它一个URL,它还你一个干净的网页文本。

1. 编写代码 (main.py)

from flask import Flask, request, jsonify
import requests
from bs4 import BeautifulSoup
import logging

logging.basicConfig(level=logging.INFO)
app = Flask(__name__)

@app.route('/scrape', methods=['POST'])
def scrape_website():
    data = request.json
    if not data or 'url' not in data:
        return jsonify({"error": "Missing 'url' in request body"}), 400

    url = data['url']
    logging.info(f"Received request to scrape URL: {url}")

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
    }

    try:
        response = requests.get(url, headers=headers, timeout=15)
        response.raise_for_status()

        soup = BeautifulSoup(response.text, 'html.parser')

        for script_or_style in soup(['script', 'style']):
            script_or_style.decompose()

        text = soup.get_text()
        lines = (line.strip() for line in text.splitlines())
        chunks = (phrase.strip() for line in lines for phrase in line.split("  "))
        clean_text = '\n'.join(chunk for chunk in chunks if chunk)

        logging.info(f"Successfully scraped content from {url}. Content length: {len(clean_text)}")
        return jsonify({"content": clean_text})

    except requests.exceptions.RequestException as e:
        logging.error(f"Failed to scrape {url}. Error: {e}")
        return jsonify({"error": f"Failed to fetch URL: {str(e)}"}), 500
    except Exception as e:
        logging.error(f"An unexpected error occurred. Error: {e}")
        return jsonify({"error": f"An unexpected error occurred: {str(e)}"}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
    
2. 定义依赖 (requirements.txt)

Flask==2.2.2
requests==2.28.1
beautifulsoup4==4.11.1
    
3. 容器化部署 (Dockerfile)

FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY main.py .
EXPOSE 5000
CMD ["python", "main.py"]
    
4. 启动服务

在包含以上三个文件的目录下,打开终端执行:


# 1. 构建Docker镜像
docker build -t competitor-scraper .

# 2. 运行容器 (我们将外部端口映射为5001)
docker run -d -p 5001:5000 --name scraper-container competitor-scraper
    

现在,你的“前线特工”已经在 http://localhost:5001/scrape 待命了!

Step 2: 配置 Dify“总指挥部”

进入 Dify,创建一个新的对话型应用,开始编排工作流。

  1. 「开始」节点:
    • 添加输入字段,变量名设为 competitor_name
  2. 「Google Search」节点:
    • Query输入: 引用变量 {{start.competitor_name}} official website
  3. 「代码执行」节点 (提取URL):
    • 输入变量: 添加一个 search_results,引用自上一步Google搜索节点的 result
    • 代码:
      
      def main(search_results: list) -> dict:
          first_url = ""
          if isinstance(search_results, list) and len(search_results) > 0:
              first_item = search_results[0]
              if isinstance(first_item, dict) and 'link' in first_item:
                  first_url = first_item['link']
          return {'first_url': first_url}
      
  4. 「HTTP请求」节点:
    • 请求方法: POST
    • URL: http://<你的电脑局域网IP>:5001/scrape (注意: 这里不能用localhost,必须是Dify能访问到的IP)。
    • Headers: Content-Typeapplication/json
    • Body (JSON):
      
      {
        "url": "{{code_1.first_url}}"
      }
      
  5. 「LLM」节点 (核心分析大脑):
    • 模型: 选择一个能力强的,如 GPT-4, Claude 3 Sonnet。
    • 上下文: 分别添加上游 Google Search 的结果和 HTTP请求 节点的 body.content
    • 提示词 (Prompt):
      
      你是一位顶级的市场分析专家。请根据我提供的【搜索引擎摘要】和【竞品官网内容】,为 "{{start.competitor_name}}" 生成一份简明扼要的竞品分析报告。
      
      **严格遵守以下规则:**
      1.  所有分析必须严格基于我提供的内容,严禁使用你的任何背景知识或进行凭空想象。
      2.  如果提供的内容不足以分析某个项目,请明确指出“信息不足,无法分析”。
      3.  使用清晰的Markdown格式输出报告。
      
      **分析框架:**
      - **公司/产品简介:** 总结其核心业务和价值主张。
      - **核心功能:** 列出3-5个主要的产品功能或服务。
      - **目标用户:** 推断其主要服务的客户群体。
      - **SWOT初步分析:**
        - **优势(Strengths):** 基于内容,总结其最突出的优点。
        - **劣势(Weaknesses):** 基于内容,推断可能存在的不足。
        - **机会(Opportunities):** 市场中可能存在的机会。
        - **威胁(Threats):** 面临的潜在威胁。
      
  6. 「直接回复」节点:
    • 引用上一步LLM节点的输出 {{llm_1.text}} 即可。

将所有节点连接起来,点击发布,大功告成!

【升华:生产级思考】—— 从Demo到实用工具

这个Demo本质上是一个小型的 RAG (检索增强生成) 应用。它让LLM在回答前,先去检索(Google)和增强(抓取网页)上下文,从而生成更准确、更具时效性的答案,极大地避免了模型幻觉。

如果想让它在真实世界更好用,我们还可以思考:

  • 动态内容抓取: 当前的抓取服务对付不了JavaScript动态加载的网站,未来可以升级为使用 Selenium 或 Playwright 等更强大的工具。
  • 信息源容错: 如果搜索到的第一个链接不是官网怎么办?可以设计一个循环或判断逻辑,尝试多个链接。
  • 深度分析: 除了官网,我们还可以让它去抓取新闻稿、社交媒体评价等,为LLM提供更全面的分析材料。

【附赠:我的工具箱】

  • 核心编排: Dify - 毫无疑问,可视化编排AI工作流的神器。
  • 外部服务: Python (Flask + Requests + BeautifulSoup) - 构建API和网页抓取的经典组合,轻量且强大。
  • 部署利器: Docker - 一次打包,到处运行,现代软件工程必备技能。
  • 分析大脑: GPT-4 / Claude 3 Sonnet - 强大的LLM是保证分析质量的核心。

【结尾:总结与回归】

通过这个实验,我们不仅构建了一个非常实用的AI助手,更重要的是,我们完整地经历了一次从需求分析、架构设计、技术攻坚到最终实现的AI应用工程落地过程。这比单纯调用一个API要酷得多!

当然,从这个Demo到真正成熟的生产级应用还有很长的路要走,但这无疑是一个完美的起点。

我是阿亚,我们下次再聊!

觉得这篇文章对你有帮助吗?请帮忙点个「赞」「在看」,让需要的人也能看到!

下一个你想看我研究什么主题?欢迎在「评论区」给我留言!

Logo

一座年轻的奋斗人之城,一个温馨的开发者之家。在这里,代码改变人生,开发创造未来!

更多推荐