page-analyzer 1.0.0 → 1.0.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.
Files changed (2) hide show
  1. package/README.md +400 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,400 @@
1
+ # page-analyzer
2
+
3
+ `page-analyzer` 是一个独立的网页分析模块,用于抓取网页、解析 DOM、提取交互元素,并结合 OpenAI 兼容的 LLM 接口生成页面区块与事件分析结果。
4
+
5
+ 它适合用于:
6
+
7
+ - 分析页面上的链接、按钮、表单、输入框等可交互节点
8
+ - 将页面 DOM 元素转换为结构化 CSV,便于后续分析
9
+ - 基于视觉区块和上下文识别页面主要功能区
10
+ - 通过 LLM 判断节点可能触发的事件类型
11
+ - 为埋点设计、页面巡检、自动化测试或站点地图分析提供基础数据
12
+
13
+ ## 功能概览
14
+
15
+ - 使用 Playwright 启动 headless Chromium 抓取真实页面内容
16
+ - 自动滚动页面并等待高度稳定,尽量覆盖懒加载内容
17
+ - 解析 HTML 中的重要元素,包括 `a`、`button`、`form`、`input`、`select`、`textarea`、标题、图片和导航区
18
+ - 收集元素文本、链接、表单动作、ARIA 信息、上下文文本、CSS 选择器和视觉区块位置
19
+ - 将交互元素导出为 CSV:`idx,blockIdx,tag,imageAlt,text,context,href`
20
+ - 使用 OpenAI 兼容接口进行页面区块分析和事件类型识别
21
+ - 支持紧凑输出或完整输出,便于在不同场景控制结果体积
22
+ - 支持高级用法:直接传入已抓取的 HTML、blocks、elementGeometries 进行分析
23
+
24
+ ## 安装
25
+
26
+ 从 npm 安装:
27
+
28
+ ```bash
29
+ npm install page-analyzer
30
+ ```
31
+
32
+ 如果在本仓库内开发:
33
+
34
+ ```bash
35
+ npm install
36
+ ```
37
+
38
+ Playwright 需要可用的 Chromium。如果运行时提示浏览器缺失,可以执行:
39
+
40
+ ```bash
41
+ npx playwright install chromium
42
+ ```
43
+
44
+ ## 环境要求
45
+
46
+ - Node.js 20.18.1 或更高版本
47
+ - 可访问目标网页的网络环境
48
+ - 一个兼容 OpenAI Chat Completions 格式的 LLM 接口
49
+
50
+ ## 快速开始
51
+
52
+ ```js
53
+ import { analyzeUrl } from 'page-analyzer';
54
+
55
+ const result = await analyzeUrl('https://example.com', {
56
+ llm: {
57
+ apiKey: process.env.LLM_API_KEY,
58
+ apiEndpoint: process.env.LLM_API_ENDPOINT,
59
+ model: process.env.LLM_MODEL
60
+ }
61
+ });
62
+
63
+ console.log(JSON.stringify(result, null, 2));
64
+ ```
65
+
66
+ 示例 `.env`:
67
+
68
+ ```bash
69
+ LLM_API_KEY=your_api_key
70
+ LLM_API_ENDPOINT=https://api.openai.com/v1/chat/completions
71
+ LLM_MODEL=gpt-4o-mini
72
+ ```
73
+
74
+ ## 运行示例脚本
75
+
76
+ 仓库内提供了 `test.js` 作为本地调试入口。它会读取项目根目录下的 `.env`,分析指定 URL,并把结果写入 `result.json`。
77
+
78
+ ```bash
79
+ npm test
80
+ ```
81
+
82
+ 也可以指定 URL:
83
+
84
+ ```bash
85
+ node test.js https://example.com
86
+ ```
87
+
88
+ 注意:`test.js` 依赖以下环境变量:
89
+
90
+ - `LLM_API_KEY`
91
+ - `LLM_API_ENDPOINT`
92
+ - `LLM_MODEL`
93
+
94
+ 缺少这些变量时会抛出配置错误。
95
+
96
+ ## API
97
+
98
+ ### analyzeUrl(url, options)
99
+
100
+ 一站式分析入口。传入 URL 后,模块会自动完成页面抓取、HTML 解析、视觉区块提取、CSV 生成和 LLM 分析。
101
+
102
+ ```js
103
+ import { analyzeUrl } from 'page-analyzer';
104
+
105
+ const result = await analyzeUrl('https://example.com', {
106
+ llm: {
107
+ apiKey: 'sk-...',
108
+ apiEndpoint: 'https://api.openai.com/v1/chat/completions',
109
+ model: 'gpt-4o-mini',
110
+ temperature: 0,
111
+ maxTokens: 8000,
112
+ timeout: 600000,
113
+ maxRetries: 3
114
+ },
115
+ showEvents: true,
116
+ showBlockIdx: true,
117
+ knownEventTypes: ['click_link', 'submit_form'],
118
+ extractorConfig: {
119
+ viewportWidth: 1440,
120
+ viewportHeight: 900,
121
+ timeoutMs: 30000
122
+ },
123
+ parserConfig: {
124
+ contextLevel: 'full',
125
+ maxTextLength: 200
126
+ }
127
+ });
128
+ ```
129
+
130
+ 参数说明:
131
+
132
+ | 参数 | 类型 | 必填 | 说明 |
133
+ | --- | --- | --- | --- |
134
+ | `url` | `string` | 是 | 要分析的页面 URL |
135
+ | `options.llm.apiKey` | `string` | 是 | LLM API key |
136
+ | `options.llm.apiEndpoint` | `string` | 是 | OpenAI 兼容的 Chat Completions endpoint |
137
+ | `options.llm.model` | `string` | 是 | 模型名称 |
138
+ | `options.llm.temperature` | `number` | 否 | LLM 温度,默认 `0` |
139
+ | `options.llm.maxTokens` | `number` | 否 | 最大输出 token 数 |
140
+ | `options.llm.timeout` | `number` | 否 | 单次请求超时时间,默认 `600000` ms |
141
+ | `options.llm.maxRetries` | `number` | 否 | LLM 请求重试次数,默认 `3` |
142
+ | `options.llm.interactionLogger` | `Function` | 否 | LLM 交互日志回调 |
143
+ | `options.knownEventTypes` | `string[]` | 否 | 已知事件类型,用于判断新增事件类型 |
144
+ | `options.parserConfig` | `object` | 否 | HTML 解析配置 |
145
+ | `options.extractorConfig` | `object` | 否 | Playwright 页面抓取配置 |
146
+ | `options.showEvents` | `boolean` | 否 | 是否返回完整事件数组和元素明细 |
147
+ | `options.showBlockIdx` | `boolean` | 否 | 是否返回 CSV 与区块索引相关字段 |
148
+
149
+ ### analyzePageEvents(input)
150
+
151
+ 高级入口。适合你已经有 HTML、视觉区块或元素几何信息,不希望 `page-analyzer` 自己打开浏览器抓取页面的场景。
152
+
153
+ ```js
154
+ import { analyzePageEvents } from 'page-analyzer';
155
+
156
+ const result = await analyzePageEvents({
157
+ html: '<html><head><title>Demo</title></head><body><a href="/pricing">Pricing</a></body></html>',
158
+ url: 'https://example.com',
159
+ blocks: [],
160
+ elementGeometries: [],
161
+ llm: {
162
+ apiKey: process.env.LLM_API_KEY,
163
+ apiEndpoint: process.env.LLM_API_ENDPOINT,
164
+ model: process.env.LLM_MODEL
165
+ },
166
+ knownEventTypes: [],
167
+ parserConfig: {
168
+ contextLevel: 'lean'
169
+ },
170
+ showEvents: true,
171
+ showBlockIdx: true,
172
+ domain: 'example.com',
173
+ nodeId: 'example-root'
174
+ });
175
+ ```
176
+
177
+ 主要输入:
178
+
179
+ | 字段 | 类型 | 必填 | 说明 |
180
+ | --- | --- | --- | --- |
181
+ | `html` | `string` | 是 | 原始 HTML |
182
+ | `url` | `string` | 是 | 页面 URL,用于解析相对链接 |
183
+ | `blocks` | `Array` | 否 | 视觉区块快照 |
184
+ | `elementGeometries` | `Array` | 否 | 页面中交互元素的几何信息 |
185
+ | `llm` | `object` | 是 | LLM 配置 |
186
+ | `knownEventTypes` | `string[]` | 否 | 已知事件类型 |
187
+ | `parserConfig` | `object` | 否 | HTML 解析配置 |
188
+ | `showEvents` | `boolean` | 否 | 是否返回完整事件数组和元素明细 |
189
+ | `showBlockIdx` | `boolean` | 否 | 是否返回 CSV 与区块索引相关字段 |
190
+ | `domain` | `string` | 否 | 分析上下文中的站点域名 |
191
+ | `nodeId` | `string` | 否 | 当前分析节点 ID |
192
+
193
+ 如果没有传入 `blocks`,模块会根据 CSV 行构造 fallback block,保证 LLM 分析流程仍然可以运行。
194
+
195
+ ## 输出结构
196
+
197
+ 默认输出会保留页面标题、解析指标和紧凑后的区块分析结果:
198
+
199
+ ```js
200
+ {
201
+ title: 'Example Domain',
202
+ parseMetrics: {
203
+ parseMs: 12,
204
+ contextBuildMs: 5,
205
+ elementsCount: 10,
206
+ linksCount: 3,
207
+ heapUsedMB: 28.4,
208
+ contextLevel: 'full'
209
+ },
210
+ analysis: {
211
+ block_analysis: {
212
+ site_summary: '...',
213
+ blocks: [
214
+ {
215
+ blockName: '...',
216
+ blockDescription: '...',
217
+ blockSemantics: [],
218
+ blockCssPath: '...',
219
+ blockPosition: {}
220
+ }
221
+ ],
222
+ stats: {
223
+ total_blocks: 4
224
+ }
225
+ }
226
+ }
227
+ }
228
+ ```
229
+
230
+ 启用 `showEvents: true` 后,输出会包含更多用于调试和下游处理的字段,例如:
231
+
232
+ - `elements`:解析出的页面元素明细
233
+ - `csvContent`:交互元素 CSV
234
+ - `links`:页面链接列表
235
+ - `analysis.events_by_node`:按节点输出的事件识别结果
236
+ - `analysis.event_types_summary`:事件类型汇总
237
+ - `analysis.new_event_types`:不在已知类型列表中的新增事件类型
238
+ - `analysis.block_analysis.possible_event_types`:页面可能存在的事件类型
239
+
240
+ 启用 `showBlockIdx: true` 后,区块结果中会额外包含 `blockIdxs`、`blockSemanticGroups`、`rowCount` 等字段,并返回 `csvContent`。
241
+
242
+ ## 配置项
243
+
244
+ ### extractorConfig
245
+
246
+ `extractorConfig` 控制 Playwright 抓取和视觉区块提取行为。
247
+
248
+ | 字段 | 默认值 | 说明 |
249
+ | --- | --- | --- |
250
+ | `timeoutMs` | `30000` | 页面导航、滚动和稳定等待超时时间 |
251
+ | `viewportWidth` | `1440` | 浏览器视口宽度 |
252
+ | `viewportHeight` | `900` | 浏览器视口高度 |
253
+ | `minBlockHeight` | `40` | 最小区块高度 |
254
+ | `minBlockWidthRatio` | `0.25` | 最小区块宽度占视口宽度比例 |
255
+ | `blockMaxHeightRatio` | `1.5` | 最大区块高度占视口高度比例 |
256
+ | `blockMaxDepth` | `15` | 区块提取最大 DOM 深度 |
257
+ | `textPreviewMaxChars` | `1200` | 区块文本预览最大长度 |
258
+
259
+ ### parserConfig
260
+
261
+ `parserConfig` 控制 HTML 元素解析和上下文提取行为。
262
+
263
+ | 字段 | 默认值 | 说明 |
264
+ | --- | --- | --- |
265
+ | `importantTags` | 内置标签列表 | 要提取的重要 DOM 标签 |
266
+ | `maxTextLength` | `200` | 元素自身文本最大长度 |
267
+ | `maxParentTextLength` | `100` | 父级文本最大长度 |
268
+ | `maxAncestorDepth` | `5` | 祖先上下文最大深度 |
269
+ | `maxNearbyTexts` | `5` | 附近文本最大数量 |
270
+ | `contextLevel` | `full` | 上下文详细程度,可选 `full` 或 `lean` |
271
+
272
+ ## 高级组件
273
+
274
+ 除主 API 外,模块还导出了一些内部组件,方便按需组合:
275
+
276
+ ```js
277
+ import {
278
+ HtmlParser,
279
+ PageExtractor,
280
+ CsvExporter,
281
+ OpenAiProvider,
282
+ BaseLlmProvider,
283
+ EventAnalyzer,
284
+ assignBlocksToElements
285
+ } from 'page-analyzer';
286
+ ```
287
+
288
+ 这些组件可以用于自定义分析流水线,例如只抓页面、只解析 HTML、只生成 CSV,或接入自定义 LLM provider。
289
+
290
+ ## LLM 接口格式
291
+
292
+ 当前内置的 `OpenAiProvider` 会向 `apiEndpoint` 发送 OpenAI Chat Completions 风格请求:
293
+
294
+ ```json
295
+ {
296
+ "model": "gpt-4o-mini",
297
+ "messages": [
298
+ {
299
+ "role": "user",
300
+ "content": "..."
301
+ }
302
+ ],
303
+ "temperature": 0
304
+ }
305
+ ```
306
+
307
+ 响应中会读取:
308
+
309
+ ```js
310
+ data.choices[0].message.content
311
+ ```
312
+
313
+ 因此,只要服务兼容这一请求和响应结构,就可以作为后端 LLM 使用。
314
+
315
+ ## 开发
316
+
317
+ 安装依赖:
318
+
319
+ ```bash
320
+ npm install
321
+ ```
322
+
323
+ 运行测试脚本:
324
+
325
+ ```bash
326
+ npm test
327
+ ```
328
+
329
+ 生成 npm 发布包预览:
330
+
331
+ ```bash
332
+ npm pack --dry-run
333
+ ```
334
+
335
+ 发布前检查:
336
+
337
+ ```bash
338
+ npm publish --dry-run
339
+ ```
340
+
341
+ ## 项目结构
342
+
343
+ ```text
344
+ page-analyzer/
345
+ index.js # 模块入口,导出主 API 和高级组件
346
+ page-extractor.js # Playwright 页面抓取与视觉区块提取
347
+ html-parser.js # HTML 解析与元素上下文提取
348
+ csv-exporter.js # 交互元素 CSV 生成
349
+ extractors/ # 区块映射、上下文提取、选择器构建
350
+ llm/
351
+ providers/ # LLM provider
352
+ analyzers/event-analyzer/ # 页面区块和事件分析逻辑
353
+ analyzers/prompts/ # LLM prompt 模板
354
+ utils/ # 事件 CSV 解析和元数据工具
355
+ models/ # 上下文数据模型
356
+ utils/ # 文本、URL、选择器工具
357
+ vendor/ # 浏览器内区块提取脚本
358
+ test.js # 本地调试脚本
359
+ ```
360
+
361
+ ## 常见问题
362
+
363
+ ### npm test 报 LLM 配置缺失
364
+
365
+ 确认项目根目录存在 `.env`,并且包含:
366
+
367
+ ```bash
368
+ LLM_API_KEY=your_api_key
369
+ LLM_API_ENDPOINT=https://api.openai.com/v1/chat/completions
370
+ LLM_MODEL=gpt-4o-mini
371
+ ```
372
+
373
+ ### Playwright 报浏览器不存在
374
+
375
+ 执行:
376
+
377
+ ```bash
378
+ npx playwright install chromium
379
+ ```
380
+
381
+ ### 目标页面内容不完整
382
+
383
+ 可以适当调大:
384
+
385
+ ```js
386
+ extractorConfig: {
387
+ timeoutMs: 60000,
388
+ viewportHeight: 1200
389
+ }
390
+ ```
391
+
392
+ 模块会自动滚动到底部并等待页面高度稳定,但如果目标站点需要登录、验证码、复杂交互或服务端限流,仍然可能拿不到完整内容。
393
+
394
+ ### LLM 返回格式解析失败
395
+
396
+ 事件分析器期望 LLM 返回 CSV section。内部会尝试自动修复格式,但如果模型输出长期不稳定,可以换用更强的模型,或降低温度。
397
+
398
+ ## License
399
+
400
+ 当前仓库没有声明 License。发布到 npm 前建议补充明确的开源许可证,例如 MIT、Apache-2.0 或私有许可证说明。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "page-analyzer",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "description": "Standalone page analysis module.",
6
6
  "main": "index.js",