上一篇 下一篇 分享链接 返回 返回顶部

从零搭建一个会总结网页的浏览器助手:部署教程与源码分享

发布人:慈云数据-客服中心 发布时间:6小时前 阅读量:0

AI浏览器 部署完整教程|附源码

随着大模型能力的不断提升,“AI 浏览器”正在成为一个非常实用的应用方向。它不是简单地在浏览器里加一个聊天窗口,而是让 AI 能够理解网页内容、总结页面信息、提取重点、辅助搜索、生成问答,甚至对网页进行结构化分析。

本文将从零开始,带你完成一个简易版 AI 浏览器助手 的部署。该项目支持:

  • 输入网页链接并抓取网页内容;
  • 对网页正文进行清洗与提取;
  • 调用大模型接口生成摘要;
  • 支持基于网页内容进行问答;
  • 提供前端页面交互;
  • 支持本地部署与服务器部署;
  • 附完整源码结构与核心代码。

本文适合有一定前端或后端基础的开发者阅读。如果你熟悉 JavaScript、Node.js 或者 Python,会更容易上手。


一、什么是 AI 浏览器?

AI 浏览器可以理解为“浏览器 + AI 助手”的组合。

传统浏览器主要负责网页访问、渲染和交互,而 AI 浏览器在此基础上增加了智能能力,例如:

  1. 网页总结
    打开一篇长文章后,AI 可以快速总结核心观点。

  2. 网页问答
    用户可以直接问:“这篇文章主要讲了什么?”“作者提出了哪些方案?”

  3. 信息提取
    从网页中提取标题、作者、发布时间、关键词、表格数据等。

  4. 辅助阅读
    将复杂内容解释成通俗语言,或者翻译成其他语言。

  5. 智能搜索
    不只是返回网页链接,而是直接整理搜索结果中的答案。

本文实现的是一个轻量级 AI 浏览器原型:用户输入网址,系统抓取网页内容,然后通过 AI 完成总结和问答。


二、项目技术栈

本项目采用前后端分离架构。

1. 前端技术

  • HTML
  • CSS
  • JavaScript
  • 原生 Fetch API

为了方便理解,本文不使用 Vue、React 等框架,而是采用最基础的 Web 技术实现界面。

2. 后端技术

  • Node.js
  • Express
  • Axios
  • Cheerio

其中:

  • Express 用于搭建后端服务;
  • Axios 用于请求网页内容和调用 AI 接口;
  • Cheerio 用于解析 HTML,提取正文文本;
  • 大模型接口可替换为 OpenAI、通义千问、DeepSeek、Kimi、智谱等。

3. 部署方式

本文会介绍两种部署方式:

  • 本地部署;
  • Linux 服务器部署。

三、项目目录结构

我们先设计项目目录。

ai-browser/
├── server/
│   ├── app.js
│   ├── ai.js
│   ├── crawler.js
│   ├── package.json
│   └── .env
├── public/
│   ├── index.html
│   ├── style.css
│   └── main.js
└── README.md

目录说明:

文件 说明
server/app.js 后端入口文件
server/ai.js AI 调用封装
server/crawler.js 网页抓取与正文提取
server/.env 环境变量配置
public/index.html 前端页面
public/style.css 页面样式
public/main.js 前端交互逻辑

四、初始化项目

首先创建项目目录:

mkdir ai-browser
cd ai-browser
mkdir server public

进入 server 目录初始化 Node.js 项目:

cd server
npm init -y

安装依赖:

npm install express axios cheerio cors dotenv

如果需要开发时自动重启服务,可以安装:

npm install nodemon -D

修改 server/package.json

{
  "name": "ai-browser-server",
  "version": "1.0.0",
  "description": "AI Browser Backend",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "dev": "nodemon app.js"
  },
  "dependencies": {
    "axios": "^1.6.0",
    "cheerio": "^1.0.0",
    "cors": "^2.8.5",
    "dotenv": "^16.0.0",
    "express": "^4.18.2"
  },
  "devDependencies": {
    "nodemon": "^3.0.0"
  }
}

五、配置环境变量

server 目录下创建 .env 文件:

PORT=3000

AI_API_KEY=你的大模型API_KEY
AI_API_URL=https://api.openai.com/v1/chat/completions
AI_MODEL=gpt-4o-mini

如果你使用的是其他模型服务,只需要修改 AI_API_URLAI_MODEL 即可。

例如使用 DeepSeek 时可能类似:

AI_API_KEY=你的DeepSeek_API_KEY
AI_API_URL=https://api.deepseek.com/chat/completions
AI_MODEL=deepseek-chat

注意:不要把 .env 文件上传到公开 GitHub 仓库,否则 API Key 可能泄露。


六、编写网页抓取模块

创建文件:

touch crawler.js

写入以下代码:

// server/crawler.js

const axios = require("axios");
const cheerio = require("cheerio");

/**
 * 抓取网页 HTML
 */
async function fetchHtml(url) {
  const response = await axios.get(url, {
    timeout: 15000,
    headers: {
      "User-Agent":
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120 Safari/537.36",
      Accept:
        "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
    }
  });

  return response.data;
}

/**
 * 提取网页正文内容
 */
function extractText(html) {
  const $ = cheerio.load(html);

  // 删除无关标签
  $("script").remove();
  $("style").remove();
  $("noscript").remove();
  $("iframe").remove();
  $("svg").remove();

  const title = $("title").text().trim();

  let text = $("body").text();

  // 清洗空白字符
  text = text
    .replace(/\s+/g, " ")
    .replace(/\n+/g, "\n")
    .trim();

  // 限制长度,避免上下文过长
  const maxLength = 12000;
  if (text.length > maxLength) {
    text = text.slice(0, maxLength);
  }

  return {
    title,
    text
  };
}

/**
 * 抓取并解析网页
 */
async function crawlPage(url) {
  if (!/^https?:\/\//i.test(url)) {
    throw new Error("URL 必须以 http:// 或 https:// 开头");
  }

  const html = await fetchHtml(url);
  const result = extractText(html);

  return result;
}

module.exports = {
  crawlPage
};

这个模块完成了三件事:

  1. 请求目标网页;
  2. 使用 Cheerio 解析 HTML;
  3. 删除无用标签并提取正文文本。

需要说明的是,不同网站的 HTML 结构不同,本文采用通用提取方式。如果是生产环境,可以结合 Readability、Mercury Parser 或自定义规则提升正文提取质量。


七、封装 AI 调用模块

创建文件:

touch ai.js

写入代码:

// server/ai.js

const axios = require("axios");

const AI_API_KEY = process.env.AI_API_KEY;
const AI_API_URL = process.env.AI_API_URL;
const AI_MODEL = process.env.AI_MODEL;

/**
 * 调用大模型
 */
async function callAI(messages) {
  if (!AI_API_KEY) {
    throw new Error("缺少 AI_API_KEY,请检查 .env 配置");
  }

  const response = await axios.post(
    AI_API_URL,
    {
      model: AI_MODEL,
      messages,
      temperature: 0.3
    },
    {
      headers: {
        Authorization: `Bearer ${AI_API_KEY}`,
        "Content-Type": "application/json"
      },
      timeout: 60000
    }
  );

  return response.data.choices[0].message.content;
}

/**
 * 总结网页内容
 */
async function summarizePage(title, text) {
  const messages = [
    {
      role: "system",
      content:
        "你是一个专业的网页阅读助手,擅长总结网页内容,请用中文输出结构清晰、简洁准确的摘要。"
    },
    {
      role: "user",
      content: `
请总结以下网页内容:

网页标题:
${title}

网页正文:
${text}

请按照以下格式输出:
1. 核心摘要
2. 主要观点
3. 关键信息
4. 适合谁阅读
`
    }
  ];

  return await callAI(messages);
}

/**
 * 基于网页内容问答
 */
async function askPage(title, text, question) {
  const messages = [
    {
      role: "system",
      content:
        "你是一个网页内容问答助手。你只能根据用户提供的网页内容回答问题。如果内容中没有答案,请明确说明无法从网页内容中判断。"
    },
    {
      role: "user",
      content: `
网页标题:
${title}

网页正文:
${text}

用户问题:
${question}

请基于网页正文回答。
`
    }
  ];

  return await callAI(messages);
}

module.exports = {
  summarizePage,
  askPage
};

这里我们封装了两个能力:

  • summarizePage:总结网页;
  • askPage:针对网页内容问答。

八、编写后端入口文件

创建 app.js

touch app.js

写入代码:

// server/app.js

require("dotenv").config();

const express = require("express");
const cors = require("cors");
const path = require("path");

const { crawlPage } = require("./crawler");
const { summarizePage, askPage } = require("./ai");

const app = express();

app.use(cors());
app.use(express.json({ limit: "2mb" }));

// 静态资源目录
app.use(express.static(path.join(__dirname, "../public")));

/**
 * 健康检查接口
 */
app.get("/api/health", (req, res) => {
  res.json({
    code: 0,
    message: "AI Browser Server is running"
  });
});

/**
 * 抓取网页并总结
 */
app.post("/api/summarize", async (req, res) => {
  try {
    const { url } = req.body;

    if (!url) {
      return res.status(400).json({
        code: 1,
        message: "缺少 url 参数"
      });
    }

    const page = await crawlPage(url);
    const summary = await summarizePage(page.title, page.text);

    res.json({
      code: 0,
      data: {
        url,
        title: page.title,
        textLength: page.text.length,
        summary
      }
    });
  } catch (error) {
    console.error(error);

    res.status(500).json({
      code: 1,
      message: error.message || "服务器错误"
    });
  }
});

/**
 * 基于网页内容问答
 */
app.post("/api/ask", async (req, res) => {
  try {
    const { url, question } = req.body;

    if (!url || !question) {
      return res.status(400).json({
        code: 1,
        message: "缺少 url 或 question 参数"
      });
    }

    const page = await crawlPage(url);
    const answer = await askPage(page.title, page.text, question);

    res.json({
      code: 0,
      data: {
        url,
        title: page.title,
        question,
        answer
      }
    });
  } catch (error) {
    console.error(error);

    res.status(500).json({
      code: 1,
      message: error.message || "服务器错误"
    });
  }
});

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log(`AI Browser Server running at http://localhost:${PORT}`);
});

到这里,后端接口已经基本完成。

我们提供了两个主要 API:

接口 方法 说明
/api/summarize POST 总结网页内容
/api/ask POST 基于网页内容问答
/api/health GET 健康检查

九、编写前端页面

回到项目根目录下的 public 目录。

创建 index.html






  
  
  AI 浏览器助手
  


  

AI 浏览器助手

输入网页链接,让 AI 帮你总结、分析和问答

AI 输出

暂无内容

十、编写页面样式

创建 style.css

/* public/style.css */

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
    "Microsoft YaHei", sans-serif;
  background: #f4f6fb;
  color: #222;
}

.app {
  max-width: 960px;
  margin: 0 auto;
  padding: 40px 20px;
}

.header {
  text-align: center;
  margin-bottom: 32px;
}

.header h1 {
  font-size: 36px;
  margin-bottom: 8px;
}

.header p {
  color: #666;
}

.card {
  background: #fff;
  border-radius: 16px;
  padding: 24px;
  margin-bottom: 20px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.06);
}

label {
  display: block;
  font-weight: 600;
  margin-bottom: 12px;
}

.url-box {
  display: flex;
  gap: 12px;
}

input,
textarea {
  width: 100%;
  border: 1px solid #dcdfe6;
  border-radius: 10px;
  padding: 14px;
  font-size: 15px;
  outline: none;
}

textarea {
  min-height: 100px;
  resize: vertical;
}

input:focus,
textarea:focus {
  border-color: #4f7cff;
}

button {
  border: none;
  background: #4f7cff;
  color: #fff;
  padding: 0 24px;
  border-radius: 10px;
  font-size: 15px;
  cursor: pointer;
  white-space: nowrap;
}

button:hover {
  background: #345eea;
}

.result-card h2 {
  margin-top: 0;
}

pre {
  white-space: pre-wrap;
  word-break: break-word;
  line-height: 1.8;
  background: #f8f9fc;
  padding: 18px;
  border-radius: 12px;
  min-height: 200px;
}

.loading {
  color: #4f7cff;
  margin-bottom: 12px;
}

.hidden {
  display: none;
}

@media (max-width: 640px) {
  .url-box {
    flex-direction: column;
  }

  button {
    height: 44px;
  }
}

十一、编写前端交互逻辑

创建 main.js

// public/main.js

const urlInput = document.getElementById("urlInput");
const questionInput = document.getElementById("questionInput");
const summaryBtn = document.getElementById("summaryBtn");
const askBtn = document.getElementById("askBtn");
const result = document.getElementById("result");
const loading = document.getElementById("loading");

function setLoading(status) {
  if (status) {
    loading.classList.remove("hidden");
  } else {
    loading.classList.add("hidden");
  }
}

function showResult(text) {
  result.textContent = text;
}

async function postJSON(url, data) {
  const response = await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(data)
  });

  return await response.json();
}

summaryBtn.addEventListener("click", async () => {
  const url = urlInput.value.trim();

  if (!url) {
    alert("请输入网页链接");
    return;
  }

  try {
    setLoading(true);
    showResult("正在抓取网页并生成摘要...");

    const res = await postJSON("/api/summarize", { url });

    if (res.code !== 0) {
      throw new Error(res.message);
    }

    showResult(
      `网页标题:${res.data.title}\n\n` +
      `正文长度:${res.data.textLength}\n\n` +
      `${res.data.summary}`
    );
  } catch (error) {
    showResult("请求失败:" + error.message);
  } finally {
    setLoading(false);
  }
});

askBtn.addEventListener("click", async () => {
  const url = urlInput.value.trim();
  const question = questionInput.value.trim();

  if (!url) {
    alert("请输入网页链接");
    return;
  }

  if (!question) {
    alert("请输入问题");
    return;
  }

  try {
    setLoading(true);
    showResult("正在分析网页并回答问题...");

    const res = await postJSON("/api/ask", {
      url,
      question
    });

    if (res.code !== 0) {
      throw new Error(res.message);
    }

    showResult(
      `网页标题:${res.data.title}\n\n` +
      `问题:${res.data.question}\n\n` +
      `回答:\n${res.data.answer}`
    );
  } catch (error) {
    showResult("请求失败:" + error.message);
  } finally {
    setLoading(false);
  }
});

前端逻辑很简单:

  1. 用户输入 URL;
  2. 点击“总结网页”调用 /api/summarize
  3. 输入问题后点击“提交问题”调用 /api/ask
  4. 将 AI 返回结果展示到页面中。

十二、本地运行项目

进入 server 目录:

cd server
npm run dev

如果不使用 nodemon,可以执行:

npm start

启动成功后,你会看到:

AI Browser Server running at http://localhost:3000

打开浏览器访问:

http://localhost:3000

输入一个网页地址,例如:

https://example.com

点击“总结网页”,等待 AI 返回结果即可。


十三、服务器部署教程

下面以 Ubuntu 服务器为例进行部署。

1. 安装 Node.js

推荐使用 Node.js 18 或以上版本。

sudo apt update
sudo apt install -y curl

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

查看版本:

node -v
npm -v

2. 上传项目代码

可以通过 Git 上传:

git clone https://你的仓库地址/ai-browser.git
cd ai-browser/server

也可以通过 scp 上传:

scp -r ai-browser root@你的服务器IP:/www/wwwroot/

3. 安装依赖

cd /www/wwwroot/ai-browser/server
npm install

4. 配置环境变量

编辑 .env

vim .env

写入:

PORT=3000
AI_API_KEY=你的API_KEY
AI_API_URL=https://api.openai.com/v1/chat/completions
AI_MODEL=gpt-4o-mini

保存退出。

5. 使用 PM2 守护进程

安装 PM2:

sudo npm install pm2 -g

启动项目:

pm2 start app.js --name ai-browser

查看运行状态:

pm2 list

查看日志:

pm2 logs ai-browser

设置开机自启:

pm2 startup
pm2 save

十四、使用 Nginx 反向代理

如果你希望通过域名访问,例如:

https://ai.example.com

可以使用 Nginx 进行反向代理。

安装 Nginx:

sudo apt install -y nginx

创建配置文件:

sudo vim /etc/nginx/conf.d/ai-browser.conf

写入:

server {
    listen 80;
    server_name ai.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

检查配置:

sudo nginx -t

重启 Nginx:

sudo systemctl restart nginx

此时访问:

http://ai.example.com

即可打开 AI 浏览器助手。

如果需要 HTTPS,可以使用 Certbot 申请免费 SSL 证书:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d ai.example.com

十五、常见问题与解决方案

1. 网页抓取失败怎么办?

可能原因包括:

  • 目标网站禁止爬虫;
  • 页面需要登录;
  • 页面内容由 JavaScript 动态渲染;
  • 网络访问受限;
  • 网站有反爬策略。

解决方案:

  • 更换 User-Agent;
  • 使用 Playwright 或 Puppeteer 渲染页面;
  • 对特定网站编写专门解析规则;
  • 增加请求重试机制。

2. AI 返回内容太慢怎么办?

可能原因:

  • 网页正文太长;
  • 模型接口响应慢;
  • 网络延迟较高。

优化方案:

  • 限制正文长度;
  • 先对正文分段摘要,再进行总摘要;
  • 使用响应速度更快的模型;
  • 增加缓存机制。

3. 摘要结果不准确怎么办?

可以优化 Prompt,例如要求模型:

  • 不要编造网页中没有的信息;
  • 输出引用依据;
  • 按标题、小节、重点进行总结;
  • 对不确定内容明确说明。

4. API Key 泄露怎么办?

如果 API Key 泄露,应立即:

  1. 到模型平台后台删除旧 Key;
  2. 重新创建新 Key;
  3. 修改服务器 .env
  4. 重启服务。

十六、项目可扩展方向

这个 AI 浏览器只是基础版本,后续可以扩展很多实用能力。

1. 浏览器插件版本

可以开发 Chrome Extension,实现:

  • 当前网页一键总结;
  • 右侧边栏 AI 助手;
  • 选中文本解释;
  • 网页翻译;
  • 文章收藏与知识库沉淀。

2. 加入向量数据库

对于长网页或多个网页,可以使用向量数据库实现 RAG 检索增强。

可选方案:

  • Chroma
  • Milvus
  • Qdrant
  • Pinecone
  • pgvector

流程如下:

  1. 抓取网页;
  2. 分段切片;
  3. 生成 Embedding;
  4. 存入向量数据库;
  5. 用户提问时召回相关片段;
  6. 再交给大模型回答。

3. 支持多轮对话

当前问答每次都会重新抓取网页,效率不高。可以增加会话 ID,将网页内容缓存起来,实现连续对话。

4. 支持搜索引擎聚合

可以接入搜索 API,让 AI 自动搜索多个网页并整合答案。

5. 增加登录系统

如果要面向用户开放,需要增加:

  • 用户注册登录;
  • 调用次数限制;
  • 会员权限;
  • 用量统计;
  • 风控系统。

十七、生产环境安全建议

如果项目要正式上线,建议至少处理以下问题:

  1. 限制 URL 类型
    防止用户请求内网地址,避免 SSRF 风险。

  2. 接口限流
    防止恶意刷接口导致 API 费用暴涨。

  3. 内容缓存
    同一个 URL 不要重复抓取和调用模型。

  4. 错误日志记录
    便于定位线上问题。

  5. API Key 后端保存
    不要把 Key 暴露在前端。

  6. 增加超时机制
    避免请求长时间挂起。

  7. 过滤敏感地址
    禁止访问 localhost127.0.0.1、内网 IP 等。

下面是一个简单的 URL 安全校验示例:

function isSafeUrl(url) {
  try {
    const parsed = new URL(url);
    const hostname = parsed.hostname;

    const blockedHosts = [
      "localhost",
      "127.0.0.1",
      "0.0.0.0"
    ];

    if (blockedHosts.includes(hostname)) {
      return false;
    }

    if (!["http:", "https:"].includes(parsed.protocol)) {
      return false;
    }

    return true;
  } catch {
    return false;
  }
}

实际生产环境还需要进一步判断内网 IP 段,例如:

  • 10.0.0.0/8
  • 172.16.0.0/12
  • 192.168.0.0/16

十八、完整部署流程总结

完整流程如下:

# 1. 创建项目
mkdir ai-browser
cd ai-browser
mkdir server public

# 2. 初始化后端
cd server
npm init -y

# 3. 安装依赖
npm install express axios cheerio cors dotenv

# 4. 编写 app.js、ai.js、crawler.js

# 5. 配置 .env
vim .env

# 6. 编写前端 index.html、style.css、main.js

# 7. 本地运行
npm run dev

# 8. 服务器部署
pm2 start app.js --name ai-browser

# 9. Nginx 反向代理
sudo nginx -t
sudo systemctl restart nginx

十九、结语

本文完整实现了一个轻量级 AI 浏览器助手,从项目初始化、网页抓取、正文提取、AI 总结、网页问答,到本地运行和服务器部署,整个流程都已经覆盖。

这个项目虽然简单,但已经具备 AI 浏览器的核心雏形:

  • 能读取网页;
  • 能理解网页;
  • 能生成摘要;
  • 能基于网页内容回答问题;
  • 能通过 Web 页面提供交互。

如果你想继续深入,可以将它扩展为 Chrome 插件、知识库系统、智能搜索引擎,甚至做成团队内部的资料阅读助手。对于个人开发者来说,这是一个非常适合练手和商业化尝试的 AI 应用方向。

目录结构
全文