Midscene.js自然语言驱动的网页自动化全指南
一、概述
网页自动化在数据抓取、UI 测试和业务流程优化中发挥着重要作用。然而,传统工具如 Selenium 和 Puppeteer 要求用户具备编程技能,编写复杂的选择器和脚本维护成本高昂。Midscene.js 通过自然语言接口革新了这一领域,用户只需描述任务(如“点击登录按钮”或“提取产品价格”),AI 即可自动执行,大幅降低技术门槛。
Midscene.js 由 web-infra-dev 团队开发,开源于 GitHub(GitHub - web-infra-dev/midscene),采用 MIT 许可。它支持多种 AI 模型,集成 Puppeteer 和 Playwright,提供丰富的功能。本文基于官网(Midscene.js)内容,全面解析其功能、模型、案例、技术细节和优化建议,为开发者提供详尽指南。
二、安装与配置
2.1. npm 安装
Midscene.js 提供两个包:
@midscene/web
:支持浏览器自动化,集成 Puppeteer/Playwright。@midscene/core
:核心功能,适合轻量级场景。
npm install @midscene/web
配置 GPT-4o:
import { overrideAIConfig } from '@midscene/web';
// 配置 AI 模型和密钥
overrideAIConfig({OPENAI_API_KEY: '你的密钥', // OpenAI API 密钥,用于访问 GPT-4omodel: 'gpt-4o' // 默认使用 GPT-4o 模型
});
本地模型(如 UI-TARS):
// 配置本地运行的 UI-TARS 模型
overrideAIConfig({model: 'ui-tars', // 开源 UI 自动化模型endpoint: 'http://localhost:5000' // 本地服务地址
});
2.1.1.环境要求
建议 Node.js 18+,安装时确保网络畅通以拉取依赖。
2.2. Chrome 扩展
通过 Chrome Web Store 安装,提供无代码体验,直接在网页输入指令即可运行。
2.2.1. 使用步骤
- 访问 Chrome Web Store,点击“添加至 Chrome”。
- 在浏览器右上角扩展图标中输入指令,如“提取页面标题”。
2.3.环境变量与高级配置
支持环境变量:
MIDSCENE_OPENAI_API_KEY
:密钥。MIDSCENE_LANGSMITH_DEBUG
:调试模式(1
)。MIDSCENE_CACHE
:启用缓存(1
)。
运行时配置:
// 高级配置示例
overrideAIConfig({OPENAI_API_KEY: '你的密钥', // 设置 API 密钥model: 'gpt-4o', // 指定模型cache: true, // 启用缓存以提升性能timeout: 20000, // 设置超时时间为 20 秒logLevel: 'verbose' // 设置详细日志级别
});
2.2.1. 本地部署
运行 UI-TARS:
docker run -p 5000:5000 ui-tars:latest # 启动 Docker 容器运行 UI-TARS 服务
配置:
// 配置本地模型连接
overrideAIConfig({model: 'ui-tars',endpoint: 'http://localhost:5000'
});
三、核心功能详解
3.1. 自然语言交互(aiAction)
通过自然语言执行操作:
// 在搜索框输入并点击搜索按钮
await agent.aiAction('在页面顶部的搜索框中输入 "JavaScript",然后点击旁边的搜索按钮');
使用技巧
- 具体性:指令越详细越好,如“点击右上角的红色按钮”。
- 多步骤:支持连续操作:
// 完整登录流程
await agent.aiAction('前往 https://example.com/login'); // 访问登录页面
await agent.aiAction('在用户名输入框中输入 "user123"'); // 输入用户名
await agent.aiAction('在密码输入框中输入 "pass123"'); // 输入密码
await agent.aiAction('点击 "登录" 按钮'); // 点击登录按钮
3.2. 数据提取(aiQuery)
提取结构化数据:
// 提取页面时间
const data = await agent.aiQuery({time: '页面左上角显示的日期和时间,格式为字符串' // 定义提取目标
});
console.log(data); // 输出:{ time: "2025-03-22 10:00 AM" }
复杂提取:
// 提取产品信息
const product = await agent.aiQuery({name: '产品名称,字符串格式', // 商品名称price: '产品价格,数字格式', // 商品价格stock: '库存状态,布尔值' // 是否有货
});
console.log(product); // 输出:{ name: "iPhone 15", price: 999, stock: true }
动态提取
const item = 'Sauce Labs Onesie'; // 定义商品名称变量
// 根据变量提取价格
const price = await agent.aiQuery({price: `"${item}" 的价格,数字格式` // 动态生成查询条件
});
console.log(price); // 输出:{ price: 7.99 }
3.3. 条件断言(aiAssert)
验证页面状态:
// 验证价格是否正确
await agent.aiAssert('"Sauce Labs Onesie" 的价格是 7.99');
复杂条件:
// 检查购物车状态
await agent.aiAssert('购物车中的商品数量大于 3'); // 验证数量
await agent.aiAssert('"结账" 按钮可见且可用'); // 验证按钮状态
错误处理
try {// 执行断言await agent.aiAssert('页面显示 "登录成功"');
} catch (e) {console.error('断言失败:', e.message); // 输出错误信息
}
3.4. 等待条件(aiWaitFor)
等待特定状态:
// 等待加载完成
await agent.aiWaitFor('加载动画不再可见', {timeout: 30000, // 设置超时为 30 秒interval: 5000 // 每 5 秒检查一次
});
结合操作
// 等待并执行
await agent.aiWaitFor('搜索结果已加载'); // 确保结果加载完成
await agent.aiAction('点击第一个搜索结果'); // 点击第一个结果
3.5. YAML 脚本(runYaml)
批量任务:
steps:- action: '点击登录按钮' # 点击登录按钮- action: '在用户名输入框中输入 "user123"' # 输入用户名- action: '在密码输入框中输入 "pass123"' # 输入密码- action: '点击提交按钮' # 提交表单
执行:
// 运行 YAML 脚本
await agent.runYaml('path/to/script.yaml');
复杂脚本
steps:- action: '前往 https://shop.com' # 访问电商网站- waitFor: '产品列表已加载' # 等待产品加载- query:products: '页面所有产品名称和价格,格式为数组 {name: string, price: number}' # 提取产品数据- assert: '"iPhone 15" 的价格低于 1000' # 验证价格
3.6. 可视化调试
生成动画和报告:
// 启用 LangSmith 调试模式
process.env.MIDSCENE_LANGSMITH_DEBUG = '1'; // 设置环境变量以输出详细日志
await agent.aiAction('点击 "注册" 按钮'); // 执行操作并生成调试报告
调试输出
报告示例:
- “定位到 ID 为 signup 的按钮”
- “点击坐标 (x: 100, y: 50),耗时 300ms”
四、支持的 AI 模型
4.1. GPT-4o
- 特点:OpenAI 多模态模型,支持文本和图像处理。
- 适用:通用自动化任务。
- 配置:
// 配置 GPT-4o 模型
overrideAIConfig({model: 'gpt-4o', // 模型名称OPENAI_API_KEY: '你的密钥' // OpenAI API 密钥
});
- 限制:无法操作跨域 iframe 或 canvas。
4.2. UI-TARS
- 特点:开源,支持图像识别和拖拽。
- 适用:复杂 UI 交互。
- 配置:
// 配置本地 UI-TARS 模型
overrideAIConfig({model: 'ui-tars', // 模型名称endpoint: 'http://localhost:5000' // 本地服务地址
});
4.3. Qwen2.5-VL
- 特点:阿里云视觉语言模型,擅长图像和文本混合处理。
- 适用:图像相关任务。
- 配置:
// 配置本地 Qwen2.5-VL 模型
overrideAIConfig({model: 'qwen2.5-vl', // 模型名称endpoint: 'http://localhost:6000' // 本地服务地址
});
模型对比
模型 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
GPT-4o | 易用、多模态、性能稳定 | 云依赖、跨域限制 | 快速原型、通用任务 |
UI-TARS | 本地部署、支持拖拽、隐私友好 | 配置复杂 | 企业应用、复杂 UI |
Qwen2.5-VL | 视觉能力强、无跨域限制 | 部署需技术支持 | 图像处理、隐私敏感任务 |
五、实际应用案例
5.1. 社交媒体自动化
自动发布 X 帖子:
// 自动发帖流程
await agent.aiAction('点击 "发帖" 按钮'); // 打开发帖框
await agent.aiAction('在文本框中输入 "Midscene.js 真好用!"'); // 输入内容
await agent.aiAction('点击 "发布" 按钮'); // 提交帖子
定时发帖:
const cron = require('node-cron');
// 每天凌晨定时发帖
cron.schedule('0 0 * * *', async () => {await agent.aiAction('发布一条帖子,内容为 "每日更新 by Midscene.js"'); // 定时发布
});
5.2. 数据收集
收集音乐会信息:
// 访问网站并提取数据
await agent.aiAction('前往 https://concert-site.com'); // 打开音乐会网站
const concertData = await agent.aiQuery({event: '音乐会名称', // 提取活动名称date: '音乐会日期', // 提取活动日期location: '举办地点' // 提取活动地点
});
console.log(concertData); // 输出结果
5.3. 测试与验证
验证电商价格:
// 检查价格和按钮状态
await agent.aiAssert('"iPhone 15" 的价格低于 1000 美元'); // 验证价格
await agent.aiAssert('"加入购物车" 按钮可见且可用'); // 验证按钮状态
5.4. 电商价格监控
监控产品价格:
async function monitorPrice() {// 访问产品页面await agent.aiAction('前往 https://shop.com/product/123');// 提取当前价格const priceData = await agent.aiQuery({price: '当前产品价格,数字格式' // 获取价格});console.log(`当前价格: ${priceData.price}`);// 检查价格是否低于阈值if (priceData.price < 800) {console.log('价格低于 800,发送通知!');// 可集成邮件通知}
}
// 每小时检查一次
setInterval(monitorPrice, 60 * 60 * 1000);
保存历史价格
const fs = require('fs');
// 保存价格历史到 CSV 文件
async function savePriceHistory() {const priceData = await agent.aiQuery({price: '当前产品价格,数字格式' // 提取价格});const record = `${new Date().toISOString()},${priceData.price}\n`; // 格式化记录fs.appendFileSync('price_history.csv', record); // 追加到文件
}
setInterval(savePriceHistory, 60 * 60 * 1000); // 每小时执行
5.5. 表单自动填写
自动填写注册表单:
async function autoFillForm() {// 访问注册页面await agent.aiAction('前往 https://example.com/register');// 等待表单加载await agent.aiWaitFor('注册表单已加载'); // 确保表单可见// 填写表单字段await agent.aiAction('在用户名输入框中输入 "testuser"'); // 输入用户名await agent.aiAction('在邮箱输入框中输入 "test@example.com"'); // 输入邮箱await agent.aiAction('在密码输入框中输入 "Password123"'); // 输入密码// 提交表单await agent.aiAction('点击 "提交" 按钮'); // 提交表单// 验证结果await agent.aiAssert('页面显示 "注册成功"'); // 检查注册是否成功
}
autoFillForm().catch(console.error);
批量填写
const users = [{ username: 'user1', email: 'user1@example.com', password: 'Pass1' },{ username: 'user2', email: 'user2@example.com', password: 'Pass2' }
];
// 批量注册多个用户
for (const user of users) {await agent.aiAction(`在用户名输入框中输入 "${user.username}"`); // 输入用户名await agent.aiAction(`在邮箱输入框中输入 "${user.email}"`); // 输入邮箱await agent.aiAction(`在密码输入框中输入 "${user.password}"`); // 输入密码await agent.aiAction('点击 "提交" 按钮'); // 提交表单
}
5.6. 动态网页抓取
抓取动态加载内容:
async function scrapeDynamicContent() {// 访问动态网页await agent.aiAction('前往 https://dynamic-site.com');// 等待内容加载await agent.aiWaitFor('动态内容已加载', { timeout: 60000 }); // 等待 60 秒// 提取文章标题和摘要const articles = await agent.aiQuery({articles: '页面所有文章标题和摘要,格式为数组 {title: string, summary: string}' // 提取动态数据});console.log(articles);// 保存到 JSON 文件fs.writeFileSync('articles.json', JSON.stringify(articles, null, 2)); // 写入文件
}
scrapeDynamicContent().catch(console.error);
处理分页
async function scrapeAllPages() {let page = 1;const allArticles = [];while (true) {// 等待当前页面加载await agent.aiWaitFor(`第 ${page} 页内容已加载`); // 确保页面加载完成// 提取数据const articles = await agent.aiQuery({articles: '当前页面所有文章标题,格式为数组 {title: string}' // 提取标题});allArticles.push(...articles.articles); // 追加到总数组// 检查是否有下一页const hasNext = await agent.aiQuery({hasNext: '是否存在 "下一页" 按钮,布尔值' // 检查分页按钮});if (!hasNext.hasNext) break; // 无下一页则退出// 点击下一页await agent.aiAction('点击 "下一页" 按钮'); // 翻页page++;}console.log(`共抓取 ${allArticles.length} 篇文章`); // 输出总数
}
scrapeAllPages();
5.7. 自动化客服
模拟客服回复:
async function autoReply() {// 访问客服页面await agent.aiAction('前往 https://support.com/chat');// 等待新消息await agent.aiWaitFor('新客户消息出现'); // 等待消息加载// 获取消息内容const message = await agent.aiQuery({message: '最新客户消息,字符串格式' // 提取最新消息});// 根据消息内容回复if (message.message.includes('价格')) {await agent.aiAction('在回复框中输入 "我们的价格请查看官网"'); // 回复价格问题} else {await agent.aiAction('在回复框中输入 "请稍等,我为您查询"'); // 默认回复}await agent.aiAction('点击 "发送" 按钮'); // 发送回复
}
// 每分钟检查一次
setInterval(autoReply, 60 * 1000);
多语言支持
async function replyInLanguage(lang) {const message = await agent.aiQuery({message: '最新客户消息,字符串格式' // 获取最新消息});// 根据语言回复if (lang === 'zh') {await agent.aiAction(`在回复框中输入 "感谢您的消息,请稍等"`);} else {await agent.aiAction(`在回复框中输入 "Thank you for your message, please wait"`);}await agent.aiAction('点击 "发送" 按钮'); // 发送回复
}
replyInLanguage('zh'); // 中文回复
六、技术细节与集成
Puppeteer 集成
const puppeteer = require('puppeteer');
const { Midscene } = require('@midscene/web');
// 启动浏览器
const browser = await puppeteer.launch({ headless: true }); // 无头模式运行
const page = await browser.newPage();
const agent = new Midscene(page); // 创建 Midscene 实例
// 执行操作
await agent.aiAction('前往 https://example.com'); // 访问页面
await agent.aiAction('点击 "注册" 按钮'); // 点击注册按钮
自定义配置
// 配置代理和无头模式
const browser = await puppeteer.launch({headless: true, // 无头模式args: ['--proxy-server=http://proxy:8080'] // 设置代理
});
缓存机制
提升性能:
// 启用默认内存缓存
overrideAIConfig({ cache: true });
// 自定义文件缓存
const fs = require('fs');
overrideAIConfig({cache: {get: (key) => fs.readFileSync(`cache/${key}.json`, 'utf8'), // 从文件读取缓存set: (key, value) => fs.writeFileSync(`cache/${key}.json`, value) // 保存到文件}
});
缓存清理
// 每天清理缓存
setInterval(() => {fs.rmSync('cache', { recursive: true, force: true }); // 删除缓存目录console.log('缓存已清理');
}, 24 * 60 * 60 * 1000); // 每天执行一次
数据隐私
本地部署 Qwen2.5-VL:
docker run -p 6000:6000 qwen2.5-vl:latest # 启动 Qwen2.5-VL 服务
配置:
// 使用本地模型保护隐私
overrideAIConfig({model: 'qwen2.5-vl',endpoint: 'http://localhost:6000'
});
隐私验证
// 测试数据是否外泄
await agent.aiAction('在输入框中输入 "敏感数据"');
console.log('检查本地服务日志,确保数据未上传云端');
七、限制与优化
限制
- 交互类型:仅支持点击、输入、滚动等,拖拽限于 UI-TARS。
- AI 稳定性:自然语言解析可能出错。
- 跨域限制:GPT-4o 无法操作跨域 iframe。
优化建议
- 提示优化:用“点击蓝色提交按钮”代替“点击按钮”。
- 重试机制:
async function retryAction(action, retries = 3) {for (let i = 0; i < retries; i++) {try {// 执行操作await agent.aiAction(action);return;} catch (e) {console.warn(`第 ${i + 1}/${retries} 次重试: ${e.message}`); // 输出重试信息await new Promise(resolve => setTimeout(resolve, 1000)); // 等待 1 秒}}throw new Error('操作失败'); // 重试失败抛出错误
}
// 重试点击操作
await retryAction('点击 "提交" 按钮');
性能监控
// 记录执行时间
const start = Date.now();
await agent.aiAction('点击 "搜索" 按钮');
console.log(`执行时间: ${Date.now() - start}ms`); // 输出耗时
并行处理
// 并行执行多个任务
const tasks = [agent.aiAction('点击 "产品" 菜单'),agent.aiAction('点击 "关于我们" 菜单')
];
await Promise.all(tasks); // 同时执行多个操作
八、社区生态与贡献
Midscene.js 的开源特性促成了活跃社区:
- 示例:X 发帖、数据收集(见 GitHub)。
- 问题跟踪:通过 GitHub Issues 提交 bug。
- 贡献:添加新模型或功能。
贡献步骤
- Fork 仓库。
- 修改代码,例如添加模型:
// 添加自定义模型
overrideAIConfig({model: 'my-model',endpoint: 'http://my-server:8000'
});
- 提交 Pull Request。
社区案例
用户贡献的 YAML 示例:
steps:- action: '前往 https://news.com' # 访问新闻网站- query:headlines: '头条新闻标题,格式为数组 {title: string}' # 提取头条
九、参考资料
- Midscene.js 官网
- GitHub 仓库
- API 文档
- 模型选择
相关文章:
Midscene.js自然语言驱动的网页自动化全指南
一、概述 网页自动化在数据抓取、UI 测试和业务流程优化中发挥着重要作用。然而,传统工具如 Selenium 和 Puppeteer 要求用户具备编程技能,编写复杂的选择器和脚本维护成本高昂。Midscene.js 通过自然语言接口革新了这一领域,用户只需描述任…...
PDF与Markdown的量子纠缠:一场由VLM导演的文档界奇幻秀
缘起:当格式界的"泰坦尼克号"撞上"黑客帝国" 某个月黑风高的夜晚,在"二进制酒吧"的霓虹灯下: PDF(西装革履地晃着威士忌): “我的每一页都像瑞士手表般精密,连华尔街的秃鹫都为我倾倒!” Markdown(穿着带洞的拖鞋): “得了吧老古董!…...
Spring Boot JSON序列化深度管控:忽略指定字段+Jackson扩展策略破解双向实体循环引用问题
一、JsonIgnore的核心原理与工作机制 1. 注解作用原理 JsonIgnore是Jackson库的核心注解之一,其工作原理基于 Jackson的AnnotationIntrospector机制。在序列化/反序列化过程中,Jackson会扫描Java对象的所有字段和方法上的注解。当检测到JsonIgnore时&a…...
msvcp140.dll是什么文件?修复丢失msvcp140.dll的方法指南
当计算机显示"msvcp140.dll未找到"的报错信息时,这实际反映了Windows系统运行机制中的一个关键环节出现断链。作为Microsoft Visual C可再发行组件包的核心动态链接库,msvcp140.dll承担着程序与系统资源之间的桥梁作用,特别是在处理…...
ES集群的部署
实验步骤 实验目的: 验证ES集群的容错性、扩展性数据分布与查询性能优化。 环境准备 1、准备两台服务器 服务器 1、10.1.1.20 cpu 2核 内存:4G 硬盘100G 2、10.1.1.21 cpu 2核 内存:4G 硬盘100G 2、修改两台静态ip 3、关闭防…...
resetForm() 方法用于重置表单
resetForm() 方法是 Vue.js 中用于重置表单的一个常见操作。下面是对这段代码的详细解析: 1. 代码作用 resetForm() 方法的作用是重置表单,将表单中的所有输入字段恢复到初始状态(通常是清空或恢复到默认值)。 2. 代码解析 re…...
Java后端API限流秘籍:高并发的防护伞与实战指南
目录导航 📜 🛡️ 为什么需要API限流?🧠 主流限流算法大解析👩💻 阿里巴巴的限流实践📏 四大黄金定律🤼 限流策略组合拳🏆 限流场景实战💻 技术实现方案🌟 最佳实践分享📈 结语与展望📚 推荐阅读 1. 🛡️ 为什么需要API限流? 在高并发环境中,未…...
团体协作项目总结Git
使用Git开放时候发现本地, 有些代码并没有被拉取到本地仓库, 又不想再commit一次, 这时候我就想到了 git commit --amend 合并提交 git commit --amend 修改git提交记录用法详解 可以将本次提交记录合并到上一次合并提交 git commit --amendgit rebase -i master^^ // 假设我…...
mysql 入门
1.已经下载过却卸载不干净?注册表清理不到位? 使用greek绿色版 强力卸载,可以一键卸载注册表里的信息。 2.如何启动mysql服务? 以管理员方式启动cmd 输入 net start mysql80 如何停止? net stop mysql80 2.将mysql客…...
1.基于TCP的简单套接字服务器实现
目录 1. TCP通信流程 2. 服务器端的通信流程 2.1 创建用于监听的套接字 2.2 绑定本地IP地址和端口 2.3 设置监听 2.4 等待接受客户端的连接请求 2.5 与客户端进行通信 2.6 客户端连接服务器 3.代码实现 client.cpp server.cpp 运行方式 在本文中,我们将…...
MantisBT在Windows10上安装部署详细步骤
MantisBT 是一款基于 Web 的开源缺陷跟踪系统,以下是在 Windows 10 上安装部署 MantisBT 的详细步骤: 1. 安装必要的环境 MantisBT 是一个基于 PHP 的 Web 应用程序,因此需要安装 Web 服务器(如 Apache)、PHP 和数据…...
zookeepernacoskafka之间的联系
一、ZooKeeper与Kafka的协同工作原理 1. 核心关系:Kafka对ZooKeeper的依赖 在Kafka 2.8版本之前,ZooKeeper是Kafka集群的“大脑”,负责管理集群元数据、协调节点状态和故障恢复。两者的协同主要通过以下关键机制实现: Broker注册…...
【QT】 布局器
参考博客:https://blog.csdn.net/Fdog_/article/details/107522283 目录 布局管理器概念常见的布局管理器及特点🔵QHBoxLayout水平布局🔵QVBoxLayout垂直布局 🔵QGridLayout网格布局 🔵QFormLayout表单布局 QT 高级布…...
力扣45.跳跃游戏
45. 跳跃游戏 II - 力扣(LeetCode) 代码区: #include<vector> class Solution {public:int jump(vector<int>& nums) {int ans[10005] ;memset(ans,1e4,sizeof(ans));ans[0]0;for(int i0;i<nums.size();i){for(int j1;j…...
【蓝桥杯】真题 路径(数论+dp)
思路 求最小公倍数LCM问题很好求,这里看似是求图最短路径,实际上由于只有[i,i21]之间存在路径,所以用线性dp效率更高,当然用bfs,dijstra,floyed也可,毕竟是填空题。 code def gcd(a,b):if a …...
敏捷需求分析之INVEST原则
INVEST原则是什么 INVEST 是用户故事的六个核心标准,由敏捷教练 Bill Wake 提出,用于确保用户故事具备可执行性和价值导向性。 1. I - Independent(独立的) 含义:用户故事应独立于其他故事,避免依赖关系。问题:若故事 A 必须等待故事 B 完成才能开发,会导致进度阻塞。…...
Apache Flink技术原理深入解析:任务执行流程全景图
前言 本文隶属于专栏《大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见大数据技术体系 思维导图 📌 引言 Apache Flink 作为一款高性能的分布式流处理引擎,其内部执行机制精妙而复杂。本文将…...
UE5小石子阴影在非常近距离才显示的问题
Unreal中采用LandscapeGrass生成的地形,在MovieRenderQueue中渲染时阴影显示距离有问题,在很近的时候才会有影子,怎么解决? 地面上通过grass生成的小石子的阴影只能在很近的时候才能显示出来,需要如下调整 r.Shadow.R…...
WebAssembly实践,性能也有局限性
个人博客原文地址 WebAssembly(简称 wasm) 是一种旨在突破 Web 性能瓶颈的技术方案。它由 W3C 官方推动,并且得到了主流浏览器的广泛支持。它的核心思想是通过运行其他高性能编程语言(比如 C、C、Rust 等)来实现复杂功…...
第一天学爬虫
阅读提示:我今天才开始尝试爬虫,写的不好请见谅。 一、准备工具 requests库:发送HTTP请求并获取网页内容。BeautifulSoup库:解析HTML页面并提取数据。pandas库:保存抓取到的数据到CSV文件中。 二、爬取步骤 发送请求…...
【FAQ】HarmonyOS SDK 闭源开放能力 —Push Kit(11)
1.问题描述: 鸿蒙push右侧图表没有正常展示。 解决方案: .jpg格式文件,头信息必须是这个“jpg:ffd8”。 2.问题描述: 安卓端App在开发者平台申请了Android应用的通知消息自分类权益,鸿蒙应用的自分类权…...
Spring WebSecurityCustomizer 的作用
Spring WebSecurityCustomizer 是 Spring Security 框架中用来 自定义 Web 安全配置 的一个接口。 它的主要作用是在开发中我们能够 精细的控制哪些请求会被 Spring Security 完全忽略,不进行任何安全检查和过滤。 我们可以把它想象成是 Spring Security 大门上的一…...
uniapp动态循环表单校验失败:初始值校验
问题现象 💥 在实现动态增减的单价输入表单时(基于uv-form组件),遇到以下诡异现象: <uv-input>的v-model绑定初始值为数字类型时,required规则失效 ❌数字类型与字符串类型校验表现不一致 🔢技术栈背景 🛠️ 框架:Vue3 + uni-appUI库:uv-ui校验方案:计算属…...
线性代数核心概念与NumPy科学计算实战全解析
前言 学习方法: 思维导图,梳理 多记忆,函数名和功能,参数 学会应用,不要钻牛角尖 一、浅解线性代数 1.1标量 标量是一个只有大小没有方向的量。在数学上,标量通常表示为一个普通的数字,如质量…...
如何理解 Apache Iceberg 与湖仓一体(Lakehouse)?
一、什么是湖仓一体(Lakehouse)? 湖仓一体是一种融合了数据湖的灵活存储能力与数据仓库的高效分析功能的现代数据架构。它通过整合两者的优势,解决了传统架构的局限性,为企业数据处理提供了更全面的解决方案。 数据湖…...
若依框架二次开发——若依集成 JSEncrypt 实现密码加密传输方式
文章目录 一、问题场景二、相关技术介绍1. RSA 加密算法2. JSEncrypt三、实现步骤1. 前端加密处理2. 后端解密处理3. 登录逻辑处理四、测试流程1. 前端测试2. 后端测试3. 运行效果五、总结一、问题场景 在 RuoYi 系统中,默认情况下,用户在登录时会将明文密码直接传输到服务器…...
Rust Web 开发新选择:探索 Hyperlane 轻量级 HTTP 服务器框架
Rust Web 开发新选择:探索 Hyperlane 轻量级 HTTP 服务器框架 在 Web 开发领域,Rust 以其高性能和内存安全性逐渐受到关注。而在众多 Web 框架中,hyperlane 作为一款轻量级、高性能的 HTTP 服务器框架,正悄然成为 Rust 生态中的明…...
初识 模版 和 STL
前言 今天简单和大家分享一下C重要的两个内容,经过之前的学习我们已经了解了C的大致语法,接下来就是C相关的库和一些操作了,他们能极大地缩小我们C语言阶段的代码量,让写代码变得轻松起来。 1.关于模版 <1>泛型编程 我们学…...
加新题了,MySQL 8.0 OCP 认证考试 题库更新
MySQL 8.0 OCP 认证考试 题库更新 MySQL 8.0 Database Administrator 考试科目:1Z0-908 近期发现,MySQL OCP认证考试题库发生变化,出现了很多新题,对此,CUUG专门收集整理了最新版本的MySQL考试原题,并会给…...
26考研——树与二叉树_树、森林(5)
408答疑 文章目录 二、树、森林树的基本概念树的定义和特性树的定义树的特性 基本术语树的基本术语和概念祖先、子孙、双亲、孩子、兄弟和堂兄弟结点的层次、度、深度和高度树的度和高度分支结点和叶结点有序树和无序树路径和路径长度 森林的基本术语和概念森林的定义森林与树的…...
26考研——图_图的基本概念(6)
408答疑 文章目录 一、图的基本概念图的定义非空性非线性结构 顶点和边的表示顶点边 有向图 & 无向图有向图有向图 G 1 G_1 G1 的表示 无向图无向图 G 2 G_2 G2 的表示 简单图 & 多重图简单图多重图 顶点的度、入度和出度顶点的度有向图的度 路径、路径长度和回路…...
笔试面试01 c/c++
基础知识 什么是数据结构?请简要描述常见的数据结构类型。 数据结构是组织和存储数据的方式,以便于高效访问和修改。常见的数据结构包括: 数组:固定大小的线性数据结构,支持随机访问。 链表:由节点组成的线…...
2025清华大学:DeepSeek教程全集(PDF+视频精讲,共10份).zip
一、资料列表 第一课:Deepseek基础入门 第二课:DeepSeek赋能职场 第三课:普通人如何抓住DeepSeek红利 第四课:让科研像聊天一样简单 第五课:DeepSeek与AI幻觉 第六课:基于DeepSeek的AI音乐词曲的创造法 第…...
消息队列(Kafka及RocketMQ等对比联系)
目录 消息队列 一、为什么使用消息队列?消息队列有什么优点/缺点?介绍下Kafka、ActiveMQ、RabbitMQ、RocketMQ有什么优点缺点,如何取舍? 1.公司业务场景是什么,这个业务场景有什么挑战,如果不用MQ有什么麻…...
Go 语言 fmt 模块的完整方法详解及示例
以下是 Go 语言 fmt 模块的完整方法详解及示例,涵盖所有核心功能: 一、输出函数 将数据写入标准输出、文件或字符串。 1. Print / Println / Printf 功能 Print: 写入标准输出,不换行。Println: 写入标准输出并换行。Printf: 格式化写入标…...
Centos 7 安装VNC服务
Centos 7 安装VNC服务 1. 安装 TigerVNC2. 设置 VNC 密码3. 创建并配置 x0vncserver 服务4. 启用并启动服务5. 检查服务状态6. 配置防火墙7. 连接 VNC问题1:出现无法安装可能是镜像源导致的。手动配置镜像源清除 YUM 缓存并重新加载 1. 安装 TigerVNC 确保已安装 TigerVNC 服务…...
3.25-3 request断言
一.request断言 if断言 案例: import requests srequests.Session() url1"http://49.233.201.254:8080/cms/manage/loginJump.do" data1{userAccount:admin,loginPwd:123456} h1{"Content-Type":"application/x-www-form-urlencoded&…...
cmakelist中添加opencv
版本选择 qt的msvc,版本2019 opencv版本 4.5.3 配置了环境变量 x64下的v14中的bin 配置头文件 {"configurations": [{"name": "Win32","includePath": ["${workspaceFolder}","d:\\QT\\6.5.3\\msvc20…...
【003安卓开发方案调研】之ReactNative技术开发安卓
基于2025年最新行业动态和搜索资料,以下是针对国内使用React Native(RN)开发安卓应用的深度分析: 一、技术成熟度评估 1. 核心架构升级 新架构全面普及:2024年起,React Native的 新架构(Fabri…...
面试中如何回答性能优化的问题
性能问题和Bug不同,后者的分析和解决思路更清晰,很多时候从应用日志(文中的应用指分布式服务下的单个节点)即可直接找到问题根源,而性能问题,其排查思路更为复杂一些。 对应用进行性能优化,是一个系统性的工程,对工程师的技术广度和技术深度都有所要求。一个简单的应用…...
使用cursor开发java案例——springboot整合elasticsearch
安装elasticsearch 打开cursor,输入如下提示词 使用springboot整合elasticsearch。其中elasticsearch服务器ip:192.168.236.134 管理员用户名elastic 管理员密码 PdQy_xfR2yLhpok*MK_ 监听端口9200点Accept all 使用idea打开生成的项目 ࿰…...
CCF-CSP认证题目练习及其题解(4
【问题描述】 涛涛最近要负责图书馆的管理工作,需要记录下每天读者的到访情况。每位读者有一个编号,每条记录用读者的编号来表示。给出读者的来访记录,请问每一条记录中的读者是第几次出现。 【输入形式】 输入的第一行包含一个整数n&#x…...
Chrome 134 版本开发者工具(DevTools)更新内容
Chrome 134 版本开发者工具(DevTools)更新内容 一、隐私与安全面板 旧的 Security 面板已演变为隐私与安全面板,并新增了一个专注于隐私的部分。在该部分中,可以: 在 DevTools 打开时,临时限制第三方 Co…...
12届蓝桥杯—货物摆放
货物摆放 题目描述 小蓝有一个超大的仓库,可以摆放很多货物。 现在,小蓝有 nn 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。 小蓝希望所…...
oracle查询归档日志使用量
1.统计最近30天的数据 SELECT TRUNC(first_time, DD) "日期", SUM(blocks * block_size) / 1024 / 1024 / 1024 "大小(GB)" FROM v$archived_log WHERE first_time > SYSDATE - 30 -- 统计最近30天的数据 GROUP BY TRUNC(first_time, DD) ORDER BY 1 D…...
Redis 发布订阅
Redis 发布订阅 概述 Redis 发布订阅(Pub/Sub)是一种消息传递模式,允许应用在多个客户端之间进行通信。在Redis中,发布订阅允许客户端订阅一个或多个频道,并在这些频道上发布消息。其他订阅了相同频道的客户端会接收到这些消息。 核心概念 频道(Channels) 频道是发…...
歌曲缓存相关功能
1. 核心组件 MusicCacheManager (音乐缓存管理器) 单例模式:确保全局只有一个实例,方便管理。 private static var instance: MusicCacheManager?static func shared() -> MusicCacheManager {if instance nil {instance MusicCacheManager()}ret…...
MySQL学习之用户管理
MySQL学习之用户管理 一、用户1、用户信息2、创建用户3、修改用户密码4、删除用户 二、数据库权限1、MySQL中的权限2、给用户授权3、回收权限 一、用户 1、用户信息 MySQL用户管理: ①、与Linux操作系统类似,MySQL中也有超级用户和普通用户之分。 ②、如…...
【第十三届“泰迪杯”数据挖掘挑战赛】【2025泰迪杯】A题解题全流程(持续更新)
【第十三届“泰迪杯”数据挖掘挑战赛】【2025泰迪杯】A题解题全流程-思路(持续更新) 写在前面: 1、A题、C题将会持续更新,陆续更新发布文章 2、赛题交流咨询Q群:1037590285 3、全家桶依旧包含: 代码、…...
算法训练营第二十三天 | 贪心算法(一)
文章目录 一、贪心算法理论基础二、Leetcode 455.分发饼干二、Leetcode 376. 摆动序列三、Leetcode 53. 最大子序和 一、贪心算法理论基础 贪心算法是一种在每一步选择中都采取当前状态下的最优决策,从而希望最终达到全局最优解的算法设计技术。 基本思想 贪心算…...