website-scrap-engine 0.8.7 → 0.9.0
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 +245 -39
- package/lib/downloader/main.d.ts.map +1 -1
- package/lib/downloader/main.js +15 -16
- package/lib/downloader/main.js.map +1 -1
- package/lib/downloader/multi.d.ts.map +1 -1
- package/lib/downloader/multi.js +3 -4
- package/lib/downloader/multi.js.map +1 -1
- package/lib/downloader/pipeline-executor-impl.d.ts +6 -3
- package/lib/downloader/pipeline-executor-impl.d.ts.map +1 -1
- package/lib/downloader/pipeline-executor-impl.js +86 -2
- package/lib/downloader/pipeline-executor-impl.js.map +1 -1
- package/lib/downloader/single.d.ts.map +1 -1
- package/lib/downloader/single.js +4 -5
- package/lib/downloader/single.js.map +1 -1
- package/lib/downloader/worker-pool.d.ts.map +1 -1
- package/lib/downloader/worker-pool.js +12 -7
- package/lib/downloader/worker-pool.js.map +1 -1
- package/lib/downloader/worker-type.d.ts +2 -2
- package/lib/downloader/worker-type.d.ts.map +1 -1
- package/lib/downloader/worker.js +2 -4
- package/lib/downloader/worker.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/life-cycle/adapters.d.ts +7 -1
- package/lib/life-cycle/adapters.d.ts.map +1 -1
- package/lib/life-cycle/adapters.js +6 -0
- package/lib/life-cycle/adapters.js.map +1 -1
- package/lib/life-cycle/default-life-cycle.d.ts.map +1 -1
- package/lib/life-cycle/default-life-cycle.js +3 -1
- package/lib/life-cycle/default-life-cycle.js.map +1 -1
- package/lib/life-cycle/default-status-listener.d.ts +4 -0
- package/lib/life-cycle/default-status-listener.d.ts.map +1 -0
- package/lib/life-cycle/default-status-listener.js +38 -0
- package/lib/life-cycle/default-status-listener.js.map +1 -0
- package/lib/life-cycle/download-resource.d.ts.map +1 -1
- package/lib/life-cycle/download-resource.js +13 -3
- package/lib/life-cycle/download-resource.js.map +1 -1
- package/lib/life-cycle/index.d.ts +1 -0
- package/lib/life-cycle/index.d.ts.map +1 -1
- package/lib/life-cycle/index.js +1 -0
- package/lib/life-cycle/index.js.map +1 -1
- package/lib/life-cycle/pipeline-executor.d.ts +10 -3
- package/lib/life-cycle/pipeline-executor.d.ts.map +1 -1
- package/lib/life-cycle/types.d.ts +56 -4
- package/lib/life-cycle/types.d.ts.map +1 -1
- package/lib/logger/default-logger.d.ts +3 -0
- package/lib/logger/default-logger.d.ts.map +1 -0
- package/lib/logger/default-logger.js +11 -0
- package/lib/logger/default-logger.js.map +1 -0
- package/lib/logger/log4js-adapter.d.ts +3 -0
- package/lib/logger/log4js-adapter.d.ts.map +1 -0
- package/lib/logger/log4js-adapter.js +143 -0
- package/lib/logger/log4js-adapter.js.map +1 -0
- package/lib/logger/logger-worker.d.ts +3 -4
- package/lib/logger/logger-worker.d.ts.map +1 -1
- package/lib/logger/logger-worker.js +21 -20
- package/lib/logger/logger-worker.js.map +1 -1
- package/lib/logger/logger.d.ts +13 -11
- package/lib/logger/logger.d.ts.map +1 -1
- package/lib/logger/logger.js +32 -14
- package/lib/logger/logger.js.map +1 -1
- package/lib/logger/types.d.ts +23 -0
- package/lib/logger/types.d.ts.map +1 -0
- package/lib/logger/types.js +2 -0
- package/lib/logger/types.js.map +1 -0
- package/lib/options.d.ts +5 -4
- package/lib/options.d.ts.map +1 -1
- package/lib/options.js +6 -4
- package/lib/options.js.map +1 -1
- package/package.json +7 -5
- package/src/downloader/main.ts +15 -14
- package/src/downloader/multi.ts +3 -5
- package/src/downloader/pipeline-executor-impl.ts +98 -2
- package/src/downloader/single.ts +4 -5
- package/src/downloader/worker-pool.ts +12 -6
- package/src/downloader/worker-type.ts +2 -2
- package/src/downloader/worker.ts +2 -7
- package/src/index.ts +2 -0
- package/src/life-cycle/adapters.ts +13 -0
- package/src/life-cycle/default-life-cycle.ts +3 -1
- package/src/life-cycle/default-status-listener.ts +40 -0
- package/src/life-cycle/download-resource.ts +13 -4
- package/src/life-cycle/index.ts +1 -0
- package/src/life-cycle/pipeline-executor.ts +16 -2
- package/src/life-cycle/types.ts +79 -3
- package/src/logger/default-logger.ts +12 -0
- package/src/logger/log4js-adapter.ts +147 -0
- package/src/logger/logger-worker.ts +24 -23
- package/src/logger/logger.ts +36 -16
- package/src/logger/types.ts +35 -0
- package/src/options.ts +11 -7
- package/lib/logger/config-logger.d.ts +0 -3
- package/lib/logger/config-logger.d.ts.map +0 -1
- package/lib/logger/config-logger.js +0 -92
- package/lib/logger/config-logger.js.map +0 -1
- package/src/logger/config-logger.ts +0 -95
package/README.md
CHANGED
|
@@ -1,42 +1,248 @@
|
|
|
1
1
|
# website-scrap-engine
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
Configurable website scraper library in TypeScript. Consumers provide a `DownloadOptions` config (which includes a `ProcessingLifeCycle`) and instantiate a downloader to recursively scrape websites to local disk.
|
|
3
4
|
|
|
4
5
|
## Features
|
|
5
|
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
6
|
+
|
|
7
|
+
- Configurable processing pipeline with hook arrays at every stage
|
|
8
|
+
- Single-thread and multi-thread (native `worker_threads`) downloaders
|
|
9
|
+
- HTML, CSS, SVG, and sitemap parsing with automatic link discovery
|
|
10
|
+
- CSS `url()` extraction and rewriting
|
|
11
|
+
- `srcset`, Open Graph meta tags, inline styles, and SVG `xlink:href` support
|
|
12
|
+
- Automatic URL-to-relative-path rewriting so saved sites work offline
|
|
13
|
+
- Streaming download support for large binary resources
|
|
14
|
+
- PQueue-based concurrency with runtime adjustment
|
|
15
|
+
- URL deduplication with configurable search-param stripping
|
|
16
|
+
- Configurable retry with exponential backoff, jitter, and `Retry-After` header support
|
|
17
|
+
- Local `file://` source support for re-processing previously saved sites
|
|
18
|
+
- Configurable logging via log4js with dedicated categories (`skip`, `retry`, `error`, `notFound`, etc.)
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install website-scrap-engine
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Requires Node.js >= 18.17.0.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
The downloader takes a path (or `file://` URL) to a module that default-exports a `DownloadOptions` object. This pattern allows worker threads to independently load the same configuration.
|
|
31
|
+
|
|
32
|
+
**Step 1: Create an options module** (e.g. `my-options.js`)
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import {lifeCycle, options, resource} from 'website-scrap-engine';
|
|
36
|
+
|
|
37
|
+
const {defaultLifeCycle} = lifeCycle;
|
|
38
|
+
const {defaultDownloadOptions} = options;
|
|
39
|
+
const {ResourceType} = resource;
|
|
40
|
+
|
|
41
|
+
const lc = defaultLifeCycle();
|
|
42
|
+
|
|
43
|
+
// Example: skip binary resources deeper than depth 2
|
|
44
|
+
lc.processBeforeDownload.push((res) => {
|
|
45
|
+
if (res.depth > 2 && res.type === ResourceType.Binary) return;
|
|
46
|
+
return res;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export default defaultDownloadOptions({
|
|
50
|
+
...lc,
|
|
51
|
+
localRoot: '/path/to/save',
|
|
52
|
+
maxDepth: 3,
|
|
53
|
+
initialUrl: ['https://example.com'],
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Step 2: Create and run the downloader**
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import path from 'path';
|
|
61
|
+
import {downloader} from 'website-scrap-engine';
|
|
62
|
+
|
|
63
|
+
const {SingleThreadDownloader} = downloader;
|
|
64
|
+
|
|
65
|
+
const d = new SingleThreadDownloader(
|
|
66
|
+
'file://' + path.resolve('my-options.js')
|
|
67
|
+
);
|
|
68
|
+
d.start();
|
|
69
|
+
d.onIdle().then(() => d.dispose());
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
For CPU-intensive workloads, use `MultiThreadDownloader` instead (see [Multi-Thread Processing](#multi-thread-processing)).
|
|
73
|
+
|
|
74
|
+
You can also pass override options as the second argument to the downloader constructor, which are merged into the options module's export:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
new SingleThreadDownloader('file://' + path.resolve('my-options.js'), {
|
|
78
|
+
localRoot: '/different/path',
|
|
79
|
+
concurrency: 8,
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Adapter Helpers
|
|
84
|
+
|
|
85
|
+
The library provides adapter functions in `lifeCycle.adapter` for common customization patterns:
|
|
86
|
+
|
|
87
|
+
| Adapter | Stage | Description |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| `skipProcess(fn)` | linkRedirect | Skip URLs matching a predicate |
|
|
90
|
+
| `dropResource(fn)` | processBeforeDownload | Mark matching resources as discard-only (replace link but don't download) |
|
|
91
|
+
| `preProcess(fn)` | processBeforeDownload | Inspect/modify resources before download |
|
|
92
|
+
| `requestRedirect(fn)` | processBeforeDownload | Rewrite the download URL |
|
|
93
|
+
| `redirectFilter(fn)` | processAfterDownload | Rewrite or discard redirect URLs |
|
|
94
|
+
| `processHtml(fn)` | processAfterDownload | Transform the parsed HTML (cheerio `$`) |
|
|
95
|
+
| `processHtmlAsync(fn)` | processAfterDownload | Async version of `processHtml` |
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import {lifeCycle} from 'website-scrap-engine';
|
|
99
|
+
|
|
100
|
+
const lc = lifeCycle.defaultLifeCycle();
|
|
101
|
+
|
|
102
|
+
// Skip all URLs containing "/api/"
|
|
103
|
+
lc.linkRedirect.push(lifeCycle.adapter.skipProcess(
|
|
104
|
+
(url) => url.includes('/api/')
|
|
105
|
+
));
|
|
106
|
+
|
|
107
|
+
// Drop images from download but still rewrite their links
|
|
108
|
+
lc.processBeforeDownload.push(lifeCycle.adapter.dropResource(
|
|
109
|
+
(res) => res.type === ResourceType.Binary && res.url.endsWith('.png')
|
|
110
|
+
));
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Architecture
|
|
114
|
+
|
|
115
|
+
### Pipeline Life Cycle
|
|
116
|
+
|
|
117
|
+
Resources are processed through a sequential pipeline of hook arrays. Each stage is an array of functions executed in order. Returning `void`/`undefined` from any function discards the resource from that stage onward.
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
init (once per downloader/worker startup)
|
|
121
|
+
|
|
|
122
|
+
v
|
|
123
|
+
URL
|
|
124
|
+
|
|
|
125
|
+
v
|
|
126
|
+
1. linkRedirect -----> skip or redirect URLs before processing
|
|
127
|
+
|
|
|
128
|
+
v
|
|
129
|
+
2. detectResourceType -> determine type (Html, Css, Binary, Svg, SiteMap, etc.)
|
|
130
|
+
|
|
|
131
|
+
v
|
|
132
|
+
3. createResource ----> build a Resource with save paths and relative replacement paths
|
|
133
|
+
|
|
|
134
|
+
v
|
|
135
|
+
4. processBeforeDownload -> filter/modify resources; link replacement in parent happens after this
|
|
136
|
+
|
|
|
137
|
+
v
|
|
138
|
+
5. download ----------> fetch resource via HTTP (loop ends early once body is set)
|
|
139
|
+
|
|
|
140
|
+
v
|
|
141
|
+
6. processAfterDownload -> parse content, discover child resources via submit() callback
|
|
142
|
+
|
|
|
143
|
+
v
|
|
144
|
+
7. saveToDisk --------> write to local filesystem
|
|
145
|
+
|
|
|
146
|
+
v
|
|
147
|
+
dispose (once per downloader shutdown / worker exit)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Consumers extend the pipeline by prepending or appending functions to any stage array via `defaultLifeCycle()`. See [Usage](#usage) for examples.
|
|
151
|
+
|
|
152
|
+
### Default Pipeline Handlers
|
|
153
|
+
|
|
154
|
+
| Stage | Default handlers |
|
|
155
|
+
|---|---|
|
|
156
|
+
| linkRedirect | `skipLinks` - filters out non-HTTP URI schemes (mailto, javascript, data, etc.) |
|
|
157
|
+
| detectResourceType | `detectResourceType` - infers type from element/context |
|
|
158
|
+
| createResource | `createResource` - builds Resource with URL resolution, save path, and replace path |
|
|
159
|
+
| download | `downloadResource`, `downloadStreamingResource`, `readOrCopyLocalResource` |
|
|
160
|
+
| processAfterDownload | `processRedirectedUrl`, `processHtml`, `processHtmlMetaRefresh`, `processSvg`, `processCss`, `processSiteMap` |
|
|
161
|
+
| saveToDisk | `saveHtmlToDisk`, `saveResourceToDisk` |
|
|
162
|
+
|
|
163
|
+
### Resource Types
|
|
164
|
+
|
|
165
|
+
Defined in `ResourceType` enum:
|
|
166
|
+
|
|
167
|
+
| Type | Encoding | Description |
|
|
168
|
+
|---|---|---|
|
|
169
|
+
| `Binary` | null | Not parsed, saved as-is |
|
|
170
|
+
| `Html` | utf8 | Parsed with cheerio, links discovered and rewritten |
|
|
171
|
+
| `Css` | utf8 | CSS `url()` references extracted and rewritten |
|
|
172
|
+
| `CssInline` | utf8 | Inline `<style>` blocks and `style` attributes |
|
|
173
|
+
| `SiteMap` | utf8 | URLs discovered but not rewritten |
|
|
174
|
+
| `Svg` | utf8 | Parsed with cheerio (same as HTML) |
|
|
175
|
+
| `StreamingBinary` | null | Streamed directly to disk, for large files |
|
|
176
|
+
|
|
177
|
+
### HTML Source Definitions
|
|
178
|
+
|
|
179
|
+
The scraper discovers linked resources from HTML using configurable source definitions. The defaults cover:
|
|
180
|
+
|
|
181
|
+
- Images: `img[src]`, `img[srcset]`, `picture source[srcset]`
|
|
182
|
+
- Styles: `link[rel="stylesheet"]`, `<style>` blocks, `[style]` attributes
|
|
183
|
+
- Scripts: `script[src]`
|
|
184
|
+
- Links: `a[href]`, `frame[src]`, `iframe[src]`
|
|
185
|
+
- Media: `video[src]`, `video[poster]`, `audio[src]`, `source[src]`, `track[src]`
|
|
186
|
+
- SVG: `*[xlink:href]`, `*[href]`
|
|
187
|
+
- Meta: `meta[property="og:image"]`, `og:audio`, `og:video` and their variants
|
|
188
|
+
- Other: `embed[src]`, `object[data]`, `input[src]`, `[background]`, `link[rel*="icon"]`, `link[rel*="preload"]`
|
|
189
|
+
|
|
190
|
+
Override via `options.sources` with an array of `{selector, attr, type}` definitions.
|
|
191
|
+
|
|
192
|
+
### Key Abstractions
|
|
193
|
+
|
|
194
|
+
- **`Resource`** (`src/resource.ts`) - Central data object carrying URL, save path, replacement path, body, and metadata. `RawResource` is the serializable subset used for cross-thread communication.
|
|
195
|
+
- **`PipelineExecutor`** (interface in `src/life-cycle/pipeline-executor.ts`, impl in `src/downloader/pipeline-executor-impl.ts`) - Orchestrates life cycle execution. `createAndProcessResource()` runs stages 1-4 in one call.
|
|
196
|
+
- **`AbstractDownloader`** (`src/downloader/main.ts`) - Base class with PQueue-based concurrency, URL deduplication, and the download loop.
|
|
197
|
+
- **`SingleThreadDownloader`** (`src/downloader/single.ts`) - Runs all pipeline stages in the main thread.
|
|
198
|
+
- **`MultiThreadDownloader`** (`src/downloader/multi.ts`) - Downloads in main thread, sends to worker pool for post-processing.
|
|
199
|
+
|
|
200
|
+
## Multi-Thread Processing
|
|
201
|
+
|
|
202
|
+
Use multi-thread processing when post-download work (HTML/CSS parsing, link discovery) is CPU-intensive.
|
|
203
|
+
|
|
204
|
+
**Main thread:**
|
|
205
|
+
- Runs the download queue with PQueue concurrency control
|
|
206
|
+
- Executes stages 1-5 (linkRedirect through download)
|
|
207
|
+
- Transfers downloaded resources to worker threads
|
|
208
|
+
- Receives discovered child resources back and enqueues non-duplicates
|
|
209
|
+
|
|
210
|
+
**Worker threads:**
|
|
211
|
+
- Receive downloaded resources from the main thread
|
|
212
|
+
- Execute stages 6-7 (processAfterDownload + saveToDisk)
|
|
213
|
+
- Parse HTML/CSS/SVG, discover child resources
|
|
214
|
+
- Run stages 1-4 on discovered children to prepare them
|
|
215
|
+
- Send prepared child resources back to the main thread as `RawResource[]`
|
|
216
|
+
|
|
217
|
+
Worker count defaults to `Math.min(concurrency, workerCount)`. The worker pool uses a 2-pass water-fill algorithm to balance tasks across workers by load.
|
|
218
|
+
|
|
219
|
+
## Logging
|
|
220
|
+
|
|
221
|
+
The library uses log4js with dedicated logger categories:
|
|
222
|
+
|
|
223
|
+
| Logger | Purpose |
|
|
224
|
+
|---|---|
|
|
225
|
+
| `skip` | Resources filtered/discarded at any pipeline stage |
|
|
226
|
+
| `skipExternal` | External resources skipped by scope |
|
|
227
|
+
| `retry` | HTTP retry attempts with backoff details |
|
|
228
|
+
| `error` | Download and processing errors |
|
|
229
|
+
| `notFound` | 404 responses |
|
|
230
|
+
| `request` / `response` | HTTP request/response logging |
|
|
231
|
+
| `complete` | Successfully processed resources |
|
|
232
|
+
| `mkdir` | Directory creation |
|
|
233
|
+
| `adjustConcurrency` | Runtime concurrency changes |
|
|
234
|
+
|
|
235
|
+
Configure logging via `options.configureLogger` and `options.logSubDir`.
|
|
236
|
+
|
|
237
|
+
## Key Dependencies
|
|
238
|
+
|
|
239
|
+
- **cheerio** - HTML/SVG parsing and manipulation
|
|
240
|
+
- **got** - HTTP client with retry logic
|
|
241
|
+
- **p-queue** - Download concurrency control
|
|
242
|
+
- **urijs** - URL resolution and path generation
|
|
243
|
+
- **css-url-parser** - CSS `url()` extraction
|
|
244
|
+
- **srcset** - `srcset` attribute parsing
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
ISC
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/downloader/main.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/downloader/main.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;AAE7B,OAAO,KAAK,EAAC,eAAe,EAAE,qBAAqB,EAAC,MAAM,eAAe,CAAC;AAE1E,OAAO,KAAK,EAAC,WAAW,EAAW,MAAM,gBAAgB,CAAC;AAM1D,OAAO,KAAK,EAAC,eAAe,EAAE,kBAAkB,EAAC,MAAM,YAAY,CAAC;AACpE,OAAO,EAAC,oBAAoB,EAAC,MAAM,6BAA6B,CAAC;AAGjE,8BAAsB,kBAAmB,YAAW,kBAAkB;IAkBvC,aAAa,EAAE,MAAM;IAjBlD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACjD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GAAG;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvF,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAqB;IACxD,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAqB;IACpD,QAAQ,CAAC,IAAI,EAAE,eAAe,CAK5B;IACF,WAAW,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,GAAG,IAAI,CAAa;IAE/D,SAAS,aAAoB,aAAa,EAAE,MAAM,EAChD,eAAe,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GAAG;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE;IAoB9E,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,IAAI,OAAO,IAAI,eAAe,CAK7B;IAED,IAAI,QAAQ,IAAI,oBAAoB,CAKnC;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,WAAW,CAAC,cAAc,EAAE,MAAM,EAErC;IAED,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAEK,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BzD,SAAS,CAAC,qBAAqB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,GAAG,IAAI;IAyBjE,QAAQ,CAAC,0BAA0B,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAE9E,oBAAoB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,GAAG,IAAI;IAStD,WAAW,CAAC,GAAG,EAAE,KAAK,GAAG,OAAO,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,IAAI;IAQpF,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED,KAAK,IAAI,IAAI;IAcb,IAAI,IAAI,IAAI;IAOZ,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAM/B"}
|
package/lib/downloader/main.js
CHANGED
|
@@ -2,7 +2,9 @@ import PQueue from 'p-queue';
|
|
|
2
2
|
import URI from 'urijs';
|
|
3
3
|
import { mergeOverrideOptions } from '../options.js';
|
|
4
4
|
import { normalizeResource, ResourceType } from '../resource.js';
|
|
5
|
-
import {
|
|
5
|
+
import { skip } from '../logger/logger.js';
|
|
6
|
+
import { setLogger } from '../logger/logger.js';
|
|
7
|
+
import { createDefaultLogger } from '../logger/default-logger.js';
|
|
6
8
|
import { importDefaultFromPath } from '../util.js';
|
|
7
9
|
import { PipelineExecutorImpl } from './pipeline-executor-impl.js';
|
|
8
10
|
export class AbstractDownloader {
|
|
@@ -23,12 +25,13 @@ export class AbstractDownloader {
|
|
|
23
25
|
this.queue = new PQueue({ concurrency: 2 });
|
|
24
26
|
this._isInit = false;
|
|
25
27
|
this._initOptions = this._asyncOptions.then(options => {
|
|
28
|
+
var _a;
|
|
26
29
|
options = mergeOverrideOptions(options, this._overrideOptions);
|
|
27
30
|
this._options = options;
|
|
28
31
|
// https://github.com/website-local/website-scrap-engine/issues/1113
|
|
29
32
|
this.queue.concurrency = options.concurrency;
|
|
30
33
|
this._pipeline = new PipelineExecutorImpl(options, options.req, options);
|
|
31
|
-
|
|
34
|
+
setLogger(((_a = options.createLogger) !== null && _a !== void 0 ? _a : createDefaultLogger)(options));
|
|
32
35
|
return this._internalInit(options).then(() => {
|
|
33
36
|
this._isInit = true;
|
|
34
37
|
});
|
|
@@ -68,9 +71,12 @@ export class AbstractDownloader {
|
|
|
68
71
|
await this._initOptions;
|
|
69
72
|
}
|
|
70
73
|
const pipeline = this.pipeline;
|
|
71
|
-
|
|
74
|
+
const submit = (url) => {
|
|
75
|
+
urlArr.push(url);
|
|
76
|
+
};
|
|
77
|
+
await pipeline.init(pipeline, this, submit);
|
|
72
78
|
// noinspection DuplicatedCode
|
|
73
|
-
for (let i = 0
|
|
79
|
+
for (let i = 0; i < urlArr.length; i++) {
|
|
74
80
|
let url = urlArr[i];
|
|
75
81
|
url = await pipeline.linkRedirect(url, null, null);
|
|
76
82
|
if (!url)
|
|
@@ -94,6 +100,7 @@ export class AbstractDownloader {
|
|
|
94
100
|
// noinspection DuplicatedCode
|
|
95
101
|
if (res.depth > this.options.maxDepth) {
|
|
96
102
|
skip.info('skipped max depth', res.url, res.refUrl, res.depth);
|
|
103
|
+
this.pipeline.notifyStatusChange(res, 'dispose');
|
|
97
104
|
return false;
|
|
98
105
|
}
|
|
99
106
|
let url;
|
|
@@ -123,18 +130,10 @@ export class AbstractDownloader {
|
|
|
123
130
|
}
|
|
124
131
|
}
|
|
125
132
|
handleError(err, cause, resource) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
notFound.error(resource.url, resource.downloadLink, resource.refUrl);
|
|
131
|
-
}
|
|
132
|
-
else if (err) {
|
|
133
|
-
error.error(cause, resource.url, resource.downloadLink, resource.refUrl, err);
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
error.error(cause, resource.url, resource.downloadLink, resource.refUrl);
|
|
137
|
-
}
|
|
133
|
+
resource.meta = resource.meta || {};
|
|
134
|
+
resource.meta['error'] = err;
|
|
135
|
+
resource.meta['errorCause'] = cause;
|
|
136
|
+
this.pipeline.notifyStatusChange(resource, 'error');
|
|
138
137
|
}
|
|
139
138
|
get downloadedCount() {
|
|
140
139
|
return this.downloadedUrl.size;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/downloader/main.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/downloader/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi.d.ts","sourceRoot":"","sources":["../../src/downloader/multi.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,EAAC,WAAW,EAAE,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAC,eAAe,EAAE,qBAAqB,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"multi.d.ts","sourceRoot":"","sources":["../../src/downloader/multi.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,EAAC,WAAW,EAAE,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAC,eAAe,EAAE,qBAAqB,EAAC,MAAM,eAAe,CAAC;AAE1E,OAAO,EAAC,kBAAkB,EAAC,MAAM,WAAW,CAAC;AAE7C,MAAM,WAAW,4BAA6B,SAAQ,qBAAqB;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,qBAAsB,SAAQ,kBAAkB;IAMlD,aAAa,EAAE,MAAM;IAE5B,OAAO,CAAC,cAAc,CAAC;IAPzB,OAAO,CAAC,KAAK,CAA6D;IAC1E,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAGtB,aAAa,EAAE,MAAM,EAC5B,eAAe,CAAC,EAAE,OAAO,CAAC,4BAA4B,CAAC,EAC/C,cAAc,CAAC,EAAE,aAAa,YAAA;IAOxC,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BhE,IAAI,IAAI,IAAI,UAAU,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAKzD;IAEK,0BAA0B,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IA+ClE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAO/B"}
|
package/lib/downloader/multi.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { WorkerPool } from './worker-pool.js';
|
|
3
|
-
import { skip } from '../logger/logger.js';
|
|
4
3
|
import { AbstractDownloader } from './main.js';
|
|
5
4
|
export class MultiThreadDownloader extends AbstractDownloader {
|
|
6
5
|
constructor(pathToOptions, overrideOptions, _workerFactory) {
|
|
@@ -29,7 +28,7 @@ export class MultiThreadDownloader extends AbstractDownloader {
|
|
|
29
28
|
return this.addInitialResource(this.options.initialUrl);
|
|
30
29
|
}
|
|
31
30
|
else {
|
|
32
|
-
return this.
|
|
31
|
+
return this.addInitialResource([]);
|
|
33
32
|
}
|
|
34
33
|
}
|
|
35
34
|
get pool() {
|
|
@@ -44,7 +43,7 @@ export class MultiThreadDownloader extends AbstractDownloader {
|
|
|
44
43
|
try {
|
|
45
44
|
r = await this.pipeline.download(res);
|
|
46
45
|
if (!r) {
|
|
47
|
-
|
|
46
|
+
await this.pipeline.notifyStatusChange(res, 'download');
|
|
48
47
|
return;
|
|
49
48
|
}
|
|
50
49
|
}
|
|
@@ -73,7 +72,7 @@ export class MultiThreadDownloader extends AbstractDownloader {
|
|
|
73
72
|
}
|
|
74
73
|
this.downloadedUrl.add(res.url);
|
|
75
74
|
if (!msg) {
|
|
76
|
-
|
|
75
|
+
await this.pipeline.notifyStatusChange(res, 'processAfterDownload');
|
|
77
76
|
return;
|
|
78
77
|
}
|
|
79
78
|
if (msg.error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi.js","sourceRoot":"","sources":["../../src/downloader/multi.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAK5C,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"multi.js","sourceRoot":"","sources":["../../src/downloader/multi.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { StaticDownloadOptions } from '../options.js';
|
|
2
|
-
import type { Resource, ResourceEncoding, ResourceType } from '../resource.js';
|
|
3
|
-
import type { DownloadResource, ProcessingLifeCycle, RequestOptions, SubmitResourceFunc } from '../life-cycle/types.js';
|
|
2
|
+
import type { RawResource, Resource, ResourceEncoding, ResourceType } from '../resource.js';
|
|
3
|
+
import type { DownloadResource, InitSubmitFunc, ProcessingLifeCycle, RequestOptions, ResourceStatus, SubmitResourceFunc } from '../life-cycle/types.js';
|
|
4
4
|
import type { PipelineExecutor } from '../life-cycle/pipeline-executor.js';
|
|
5
5
|
import type { Cheerio } from '../types.js';
|
|
6
6
|
import type { DownloaderWithMeta } from './types.js';
|
|
@@ -13,7 +13,7 @@ export declare class PipelineExecutorImpl implements PipelineExecutor {
|
|
|
13
13
|
requestOptions: RequestOptions;
|
|
14
14
|
options: StaticDownloadOptions;
|
|
15
15
|
constructor(lifeCycle: ProcessingLifeCycle, requestOptions: RequestOptions, options: StaticDownloadOptions);
|
|
16
|
-
init(pipeline: PipelineExecutor, downloader?: DownloaderWithMeta): Promise<void>;
|
|
16
|
+
init(pipeline: PipelineExecutor, downloader?: DownloaderWithMeta, submit?: InitSubmitFunc): Promise<void>;
|
|
17
17
|
createAndProcessResource(rawUrl: string, defaultType: ResourceType, depth: number | void | null, element: Cheerio | null, parent: Resource): Promise<Resource | void>;
|
|
18
18
|
linkRedirect(url: string, element: Cheerio | null, parent: Resource | null): Promise<string | void>;
|
|
19
19
|
detectResourceType(url: string, type: ResourceType, element: Cheerio | null, parent: Resource | null): Promise<ResourceType | void>;
|
|
@@ -29,5 +29,8 @@ export declare class PipelineExecutorImpl implements PipelineExecutor {
|
|
|
29
29
|
processAfterDownload(res: DownloadResource, submit: SubmitResourceFunc, options?: StaticDownloadOptions): Promise<DownloadResource | void>;
|
|
30
30
|
saveToDisk(res: DownloadResource, options?: StaticDownloadOptions): Promise<DownloadResource | void>;
|
|
31
31
|
dispose(pipeline: PipelineExecutor, downloader: DownloaderWithMeta, workerInfo?: WorkerInfo, workerExitCode?: number): Promise<void>;
|
|
32
|
+
notifyStatusChange(res: Resource | RawResource, status: ResourceStatus): Promise<void>;
|
|
33
|
+
private _checkExistingResource;
|
|
34
|
+
private _getExistingFileMtime;
|
|
32
35
|
}
|
|
33
36
|
//# sourceMappingURL=pipeline-executor-impl.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline-executor-impl.d.ts","sourceRoot":"","sources":["../../src/downloader/pipeline-executor-impl.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pipeline-executor-impl.d.ts","sourceRoot":"","sources":["../../src/downloader/pipeline-executor-impl.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { existsSync, statSync } from 'node:fs';
|
|
1
3
|
/**
|
|
2
4
|
* Pipeline executor
|
|
3
5
|
*/
|
|
@@ -7,11 +9,11 @@ export class PipelineExecutorImpl {
|
|
|
7
9
|
this.requestOptions = requestOptions;
|
|
8
10
|
this.options = options;
|
|
9
11
|
}
|
|
10
|
-
async init(pipeline, downloader) {
|
|
12
|
+
async init(pipeline, downloader, submit) {
|
|
11
13
|
if (!this.lifeCycle.init)
|
|
12
14
|
return;
|
|
13
15
|
for (const init of this.lifeCycle.init) {
|
|
14
|
-
await init(pipeline, downloader);
|
|
16
|
+
await init(pipeline, downloader, submit);
|
|
15
17
|
}
|
|
16
18
|
}
|
|
17
19
|
async createAndProcessResource(rawUrl, defaultType, depth, element, parent) {
|
|
@@ -91,6 +93,22 @@ export class PipelineExecutorImpl {
|
|
|
91
93
|
if (!options) {
|
|
92
94
|
options = this.options;
|
|
93
95
|
}
|
|
96
|
+
if (this.lifeCycle.existingResource) {
|
|
97
|
+
const action = this._checkExistingResource(res, 'download');
|
|
98
|
+
if (action === 'skip') {
|
|
99
|
+
res.shouldBeDiscardedFromDownload = true;
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
if (action === 'ifModifiedSince') {
|
|
103
|
+
const mtime = this._getExistingFileMtime(res);
|
|
104
|
+
if (mtime) {
|
|
105
|
+
requestOptions = Object.assign({}, requestOptions);
|
|
106
|
+
requestOptions.headers = Object.assign({}, requestOptions.headers, {
|
|
107
|
+
'if-modified-since': mtime
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
94
112
|
let downloadedResource = res;
|
|
95
113
|
for (const download of this.lifeCycle.download) {
|
|
96
114
|
if ((downloadedResource = await download(downloadedResource, requestOptions, options, this))
|
|
@@ -125,9 +143,31 @@ export class PipelineExecutorImpl {
|
|
|
125
143
|
return downloadedResource;
|
|
126
144
|
}
|
|
127
145
|
async saveToDisk(res, options) {
|
|
146
|
+
var _a, _b, _c;
|
|
128
147
|
if (!options) {
|
|
129
148
|
options = this.options;
|
|
130
149
|
}
|
|
150
|
+
if (this.lifeCycle.existingResource) {
|
|
151
|
+
const action = this._checkExistingResource(res, 'saveToDisk');
|
|
152
|
+
if (action === 'skip' || action === 'skipSave') {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
if (action === 'ifModifiedSince') {
|
|
156
|
+
const remoteLastMod = (_b = (_a = res.meta) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? void 0 : _b['last-modified'];
|
|
157
|
+
if (remoteLastMod) {
|
|
158
|
+
const localPath = path.join((_c = res.localRoot) !== null && _c !== void 0 ? _c : this.options.localRoot, decodeURI(res.savePath));
|
|
159
|
+
try {
|
|
160
|
+
const localMtime = statSync(localPath).mtime;
|
|
161
|
+
if (new Date(remoteLastMod) <= localMtime) {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch (_d) {
|
|
166
|
+
// file removed between check and stat, proceed with save
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
131
171
|
let downloadedResource = res;
|
|
132
172
|
for (const saveToDisk of this.lifeCycle.saveToDisk) {
|
|
133
173
|
if ((downloadedResource = await saveToDisk(downloadedResource, options, this))
|
|
@@ -146,5 +186,49 @@ export class PipelineExecutorImpl {
|
|
|
146
186
|
await dispose(pipeline, downloader, workerInfo, workerExitCode);
|
|
147
187
|
}
|
|
148
188
|
}
|
|
189
|
+
async notifyStatusChange(res, status) {
|
|
190
|
+
var _a;
|
|
191
|
+
if (!((_a = this.lifeCycle.statusChange) === null || _a === void 0 ? void 0 : _a.length))
|
|
192
|
+
return;
|
|
193
|
+
for (const listener of this.lifeCycle.statusChange) {
|
|
194
|
+
try {
|
|
195
|
+
const r = listener(res, status, this.options, this);
|
|
196
|
+
if (r)
|
|
197
|
+
await r;
|
|
198
|
+
}
|
|
199
|
+
catch (_b) {
|
|
200
|
+
// swallow
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
_checkExistingResource(res, stage) {
|
|
205
|
+
var _a;
|
|
206
|
+
const localPath = path.join((_a = res.localRoot) !== null && _a !== void 0 ? _a : this.options.localRoot, decodeURI(res.savePath));
|
|
207
|
+
if (!existsSync(localPath))
|
|
208
|
+
return undefined;
|
|
209
|
+
let stat;
|
|
210
|
+
try {
|
|
211
|
+
stat = statSync(localPath);
|
|
212
|
+
}
|
|
213
|
+
catch (_b) {
|
|
214
|
+
// TOCTOU: file deleted between existsSync and statSync
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
if (!stat.isFile())
|
|
218
|
+
return undefined;
|
|
219
|
+
return this.lifeCycle.existingResource({
|
|
220
|
+
res, stage, localPath, stat, options: this.options
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
_getExistingFileMtime(res) {
|
|
224
|
+
var _a;
|
|
225
|
+
const localPath = path.join((_a = res.localRoot) !== null && _a !== void 0 ? _a : this.options.localRoot, decodeURI(res.savePath));
|
|
226
|
+
try {
|
|
227
|
+
return statSync(localPath).mtime.toUTCString();
|
|
228
|
+
}
|
|
229
|
+
catch (_b) {
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
149
233
|
}
|
|
150
234
|
//# sourceMappingURL=pipeline-executor-impl.js.map
|