smart-image-scraper-mcp 2.7.0 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/package.json +1 -1
- package/src/index.js +4 -0
- package/src/providers/bingScraper.js +3 -4
- package/src/providers/googleScraper.js +3 -3
- package/src/services/orchestrator.js +10 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
## ✨ 核心特性
|
|
9
9
|
|
|
10
|
-
### 🚀 高性能架构 (v2.
|
|
10
|
+
### 🚀 高性能架构 (v2.8.0)
|
|
11
11
|
- **多请求并行**:同时处理 5 个 MCP 请求
|
|
12
12
|
- **并行翻页搜索**:同时获取多页结果,速度提升 5x
|
|
13
13
|
- **HTTP 连接池**:Keep-Alive 复用 TCP 连接
|
|
@@ -86,6 +86,8 @@ npm install
|
|
|
86
86
|
- "下载 20 张高清风景壁纸"
|
|
87
87
|
- "找一些人物头像图片"
|
|
88
88
|
|
|
89
|
+
> ⚠️ **重要限制**:同一会话中连续调用不要超过 5 次!需要多种类型图片时,使用批量查询(逗号分隔关键词)。
|
|
90
|
+
|
|
89
91
|
## Tool Schema
|
|
90
92
|
|
|
91
93
|
### smart_scraper
|
|
@@ -281,6 +283,7 @@ npm test
|
|
|
281
283
|
|
|
282
284
|
| 版本 | 日期 | 主要更新 |
|
|
283
285
|
|------|------|----------|
|
|
286
|
+
| 2.8.0 | 2026-02 | 添加熔断机制:30秒全局超时、快速失败返回、降低搜索超时至8秒 |
|
|
284
287
|
| 2.7.0 | 2026-02 | 新增质量控制:quality 参数(fast/balanced/high)、minFileSize 文件大小过滤 |
|
|
285
288
|
| 2.4.0 | 2026-02 | 修复所有分析问题:超时策略统一、缓存键一致、版本号动态读取 |
|
|
286
289
|
| 2.3.0 | 2026-02 | 性能优化:HTTP 连接池、并行翻页搜索、内存泄漏修复 |
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -65,6 +65,10 @@ const SMART_SCRAPER_TOOL = {
|
|
|
65
65
|
- 正方形: square_1080(1080x1080), square_512(512x512)
|
|
66
66
|
- 社交媒体: instagram(1080x1080), twitter(1200x675), facebook(1200x630)
|
|
67
67
|
|
|
68
|
+
【⚠️ 重要限制】
|
|
69
|
+
- 同一会话中连续调用此工具不要超过5次!超过后可能无响应
|
|
70
|
+
- 当用户需要多种类型图片时,必须使用批量查询(逗号分隔),而不是多次调用
|
|
71
|
+
|
|
68
72
|
【调用示例】
|
|
69
73
|
1. 搜索5张猫的图片: {"query":"可爱的猫","mode":"link","count":5}
|
|
70
74
|
2. 下载10张高清风景图: {"query":"风景","mode":"download","count":10,"size":"large"}
|
|
@@ -49,11 +49,10 @@ export class BingScraper extends BaseScraper {
|
|
|
49
49
|
try {
|
|
50
50
|
const response = await withRetry(
|
|
51
51
|
() => httpClient.get(searchUrl, {
|
|
52
|
-
timeout:
|
|
53
|
-
|
|
54
|
-
signal: AbortSignal.timeout(15000),
|
|
52
|
+
timeout: 8000, // 8秒超时,快速失败
|
|
53
|
+
signal: AbortSignal.timeout(8000),
|
|
55
54
|
}),
|
|
56
|
-
{ maxRetries:
|
|
55
|
+
{ maxRetries: 1, retryCondition: isRetryableError } // 只重试1次
|
|
57
56
|
);
|
|
58
57
|
|
|
59
58
|
if (response.status !== 200) {
|
|
@@ -48,8 +48,8 @@ export class GoogleScraper extends BaseScraper {
|
|
|
48
48
|
try {
|
|
49
49
|
const response = await withRetry(
|
|
50
50
|
() => httpClient.get(searchUrl, {
|
|
51
|
-
timeout:
|
|
52
|
-
signal: AbortSignal.timeout(
|
|
51
|
+
timeout: 8000, // 8秒超时,快速失败
|
|
52
|
+
signal: AbortSignal.timeout(8000),
|
|
53
53
|
headers: {
|
|
54
54
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
55
55
|
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
|
@@ -57,7 +57,7 @@ export class GoogleScraper extends BaseScraper {
|
|
|
57
57
|
'Referer': 'https://www.google.com/',
|
|
58
58
|
},
|
|
59
59
|
}),
|
|
60
|
-
{ maxRetries:
|
|
60
|
+
{ maxRetries: 1, retryCondition: isRetryableError } // 只重试1次
|
|
61
61
|
);
|
|
62
62
|
|
|
63
63
|
if (response.status !== 200) {
|
|
@@ -310,10 +310,19 @@ export class Orchestrator {
|
|
|
310
310
|
async execute(params) {
|
|
311
311
|
metrics.recordRequest();
|
|
312
312
|
const requestId = `req_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`;
|
|
313
|
+
const GLOBAL_TIMEOUT = 30000; // 30秒全局超时
|
|
313
314
|
|
|
314
315
|
try {
|
|
315
316
|
logger.info(`[Orchestrator] Starting request: ${requestId}`);
|
|
316
|
-
|
|
317
|
+
|
|
318
|
+
// 添加全局超时熔断机制
|
|
319
|
+
const result = await Promise.race([
|
|
320
|
+
this._executeInternal(params),
|
|
321
|
+
new Promise((_, reject) =>
|
|
322
|
+
setTimeout(() => reject(new Error('REQUEST_TIMEOUT: 请求超时(30秒),请稍后重试')), GLOBAL_TIMEOUT)
|
|
323
|
+
)
|
|
324
|
+
]);
|
|
325
|
+
|
|
317
326
|
result.requestId = requestId;
|
|
318
327
|
logger.info(`[Orchestrator] Completed request: ${requestId}`);
|
|
319
328
|
return result;
|