@hanivanrizky/nestjs-browser-action 0.21.0 → 0.23.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 +78 -45
- package/dist/browser-action.module-definition.d.ts +1 -0
- package/dist/browser-action.module.d.ts +7 -0
- package/dist/browser-action.module.js +203 -28
- package/dist/browser-action.module.js.map +1 -1
- package/dist/common/index.d.ts +1 -0
- package/dist/common/index.js +18 -0
- package/dist/common/index.js.map +1 -0
- package/dist/common/tokens.d.ts +9 -0
- package/dist/common/tokens.js +47 -0
- package/dist/common/tokens.js.map +1 -0
- package/dist/constants/browser-action.constants.d.ts +1 -0
- package/dist/constants/browser-action.constants.js +2 -1
- package/dist/constants/browser-action.constants.js.map +1 -1
- package/dist/decorators/index.d.ts +1 -0
- package/dist/decorators/index.js +1 -0
- package/dist/decorators/index.js.map +1 -1
- package/dist/decorators/inject-browser.decorator.d.ts +2 -1
- package/dist/decorators/inject-browser.decorator.js +2 -1
- package/dist/decorators/inject-browser.decorator.js.map +1 -1
- package/dist/decorators/inject-page-controller.decorator.d.ts +2 -0
- package/dist/decorators/inject-page-controller.decorator.js +8 -0
- package/dist/decorators/inject-page-controller.decorator.js.map +1 -0
- package/dist/decorators/inject-page.decorator.d.ts +2 -1
- package/dist/decorators/inject-page.decorator.js +2 -1
- package/dist/decorators/inject-page.decorator.js.map +1 -1
- package/dist/examples/named-browser-example.d.ts +1 -0
- package/dist/examples/named-browser-example.js +183 -0
- package/dist/examples/named-browser-example.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/browser-action-options.d.ts +6 -0
- package/dist/operators/capture.operator.d.ts +11 -0
- package/dist/operators/capture.operator.js +62 -0
- package/dist/operators/capture.operator.js.map +1 -0
- package/dist/operators/container.operator.d.ts +13 -0
- package/dist/operators/container.operator.js +149 -0
- package/dist/operators/container.operator.js.map +1 -0
- package/dist/operators/extraction.operator.d.ts +22 -0
- package/dist/operators/extraction.operator.js +204 -0
- package/dist/operators/extraction.operator.js.map +1 -0
- package/dist/operators/index.d.ts +5 -0
- package/dist/operators/index.js +14 -0
- package/dist/operators/index.js.map +1 -0
- package/dist/operators/pagination.operator.d.ts +24 -0
- package/dist/operators/pagination.operator.js +182 -0
- package/dist/operators/pagination.operator.js.map +1 -0
- package/dist/operators/workflow.operator.d.ts +35 -0
- package/dist/operators/workflow.operator.js +501 -0
- package/dist/operators/workflow.operator.js.map +1 -0
- package/dist/services/browser-action.service.d.ts +6 -29
- package/dist/services/browser-action.service.js +28 -968
- package/dist/services/browser-action.service.js.map +1 -1
- package/dist/services/browser-health-check.d.ts +11 -0
- package/dist/services/browser-health-check.js +30 -0
- package/dist/services/browser-health-check.js.map +1 -0
- package/dist/services/browser-holder.d.ts +7 -0
- package/dist/services/browser-holder.js +26 -0
- package/dist/services/browser-holder.js.map +1 -0
- package/dist/services/browser-manager.service.js.map +1 -1
- package/dist/services/browser-pool.service.d.ts +0 -4
- package/dist/services/browser-pool.service.js +12 -103
- package/dist/services/browser-pool.service.js.map +1 -1
- package/dist/services/named-browser-shutdown.d.ts +11 -0
- package/dist/services/named-browser-shutdown.js +51 -0
- package/dist/services/named-browser-shutdown.js.map +1 -0
- package/dist/services/page-controller.d.ts +39 -0
- package/dist/services/page-controller.js +325 -0
- package/dist/services/page-controller.js.map +1 -0
- package/dist/services/page-session.d.ts +26 -0
- package/dist/services/page-session.js +135 -0
- package/dist/services/page-session.js.map +1 -0
- package/dist/services/page.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/browser-launcher.d.ts +6 -0
- package/dist/utils/browser-launcher.js +100 -0
- package/dist/utils/browser-launcher.js.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6DAA2C;AAC3C,0DAAwC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6DAA2C;AAC3C,0DAAwC;AACxC,qEAAmD"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { Inject } from '@nestjs/common';
|
|
2
|
+
export declare const InjectBrowser: (name?: string) => ReturnType<typeof Inject>;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.InjectBrowser = void 0;
|
|
4
4
|
const common_1 = require("@nestjs/common");
|
|
5
|
-
const
|
|
5
|
+
const tokens_1 = require("../common/tokens");
|
|
6
|
+
const InjectBrowser = (name = 'default') => (0, common_1.Inject)((0, tokens_1.getBrowserToken)(name));
|
|
6
7
|
exports.InjectBrowser = InjectBrowser;
|
|
7
8
|
//# sourceMappingURL=inject-browser.decorator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inject-browser.decorator.js","sourceRoot":"","sources":["../../src/decorators/inject-browser.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;
|
|
1
|
+
{"version":3,"file":"inject-browser.decorator.js","sourceRoot":"","sources":["../../src/decorators/inject-browser.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AACxC,6CAAmD;AAM5C,MAAM,aAAa,GAAG,CAAC,IAAI,GAAG,SAAS,EAA6B,EAAE,CAC3E,IAAA,eAAM,EAAC,IAAA,wBAAe,EAAC,IAAI,CAAC,CAAC,CAAC;AADnB,QAAA,aAAa,iBACM"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InjectPageController = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const tokens_1 = require("../common/tokens");
|
|
6
|
+
const InjectPageController = (page, name = 'default') => (0, common_1.Inject)((0, tokens_1.getPageControllerToken)(page, name));
|
|
7
|
+
exports.InjectPageController = InjectPageController;
|
|
8
|
+
//# sourceMappingURL=inject-page-controller.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-page-controller.decorator.js","sourceRoot":"","sources":["../../src/decorators/inject-page-controller.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AACxC,6CAA0D;AAMnD,MAAM,oBAAoB,GAAG,CAClC,IAAY,EACZ,IAAI,GAAG,SAAS,EACW,EAAE,CAAC,IAAA,eAAM,EAAC,IAAA,+BAAsB,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAH9D,QAAA,oBAAoB,wBAG0C"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { Inject } from '@nestjs/common';
|
|
2
|
+
export declare const InjectPage: (page: string, name?: string) => ReturnType<typeof Inject>;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.InjectPage = void 0;
|
|
4
4
|
const common_1 = require("@nestjs/common");
|
|
5
|
-
const
|
|
5
|
+
const tokens_1 = require("../common/tokens");
|
|
6
|
+
const InjectPage = (page, name = 'default') => (0, common_1.Inject)((0, tokens_1.getPageToken)(page, name));
|
|
6
7
|
exports.InjectPage = InjectPage;
|
|
7
8
|
//# sourceMappingURL=inject-page.decorator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inject-page.decorator.js","sourceRoot":"","sources":["../../src/decorators/inject-page.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;
|
|
1
|
+
{"version":3,"file":"inject-page.decorator.js","sourceRoot":"","sources":["../../src/decorators/inject-page.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AACxC,6CAAgD;AAMzC,MAAM,UAAU,GAAG,CACxB,IAAY,EACZ,IAAI,GAAG,SAAS,EACW,EAAE,CAAC,IAAA,eAAM,EAAC,IAAA,qBAAY,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAHpD,QAAA,UAAU,cAG0C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var CrawlerService_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
const core_1 = require("@nestjs/core");
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const index_1 = require("../index");
|
|
19
|
+
let CrawlerService = CrawlerService_1 = class CrawlerService {
|
|
20
|
+
login;
|
|
21
|
+
products;
|
|
22
|
+
logger = new common_1.Logger(CrawlerService_1.name);
|
|
23
|
+
constructor(login, products) {
|
|
24
|
+
this.login = login;
|
|
25
|
+
this.products = products;
|
|
26
|
+
}
|
|
27
|
+
async run() {
|
|
28
|
+
this.logger.log('Starting run — browser: "stealth", pages: login, products');
|
|
29
|
+
const loginResult = await this.runLogin();
|
|
30
|
+
const products = await this.runProductsScrape();
|
|
31
|
+
const title = await this.runCurrentPageExtract();
|
|
32
|
+
const concurrent = await this.runConcurrent();
|
|
33
|
+
this.logger.log('Run complete');
|
|
34
|
+
return { loginResult, products, title, concurrent };
|
|
35
|
+
}
|
|
36
|
+
async runConcurrent() {
|
|
37
|
+
this.logger.log('[concurrent] login workflow + products scrape in parallel');
|
|
38
|
+
const startedAt = Date.now();
|
|
39
|
+
try {
|
|
40
|
+
const [loginResult, products] = await Promise.all([
|
|
41
|
+
this.runLogin(),
|
|
42
|
+
this.runProductsScrape(),
|
|
43
|
+
]);
|
|
44
|
+
this.logger.log(`[concurrent] both done in ${Date.now() - startedAt}ms — login: "${loginResult.data.username}", products: ${products.results.length}`);
|
|
45
|
+
return { loginResult, products };
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
this.logger.error(`[concurrent] failed after ${Date.now() - startedAt}ms`, err instanceof Error ? err.stack : String(err));
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async runLogin() {
|
|
53
|
+
this.logger.log('[login] navigating + running login workflow');
|
|
54
|
+
const startedAt = Date.now();
|
|
55
|
+
try {
|
|
56
|
+
const loginResult = await this.login.scrapeWithWorkflow('https://www.scrapingcourse.com/login', {
|
|
57
|
+
version: '1.0',
|
|
58
|
+
actions: [
|
|
59
|
+
{
|
|
60
|
+
action: 'type',
|
|
61
|
+
target: { type: 'css', value: '#email' },
|
|
62
|
+
value: 'admin@example.com',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
action: 'type',
|
|
66
|
+
target: { type: 'css', value: '#password' },
|
|
67
|
+
value: 'password',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
action: 'click',
|
|
71
|
+
target: { type: 'css', value: 'button[type="submit"]' },
|
|
72
|
+
options: { waitForNavigation: true },
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: 'username',
|
|
76
|
+
action: 'extract',
|
|
77
|
+
target: { type: 'css', value: 'span.text-lg.font-semibold' },
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
this.logger.log(`[login] logged in as "${loginResult.data.username}" (${Date.now() - startedAt}ms)`);
|
|
82
|
+
return loginResult;
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
this.logger.error(`[login] workflow failed after ${Date.now() - startedAt}ms`, err instanceof Error ? err.stack : String(err));
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async runProductsScrape() {
|
|
90
|
+
this.logger.log('[products] scraping product listing');
|
|
91
|
+
const startedAt = Date.now();
|
|
92
|
+
try {
|
|
93
|
+
const products = await this.products.evaluateWebsite({
|
|
94
|
+
url: 'https://www.scrapingcourse.com/ecommerce/',
|
|
95
|
+
patterns: [
|
|
96
|
+
{
|
|
97
|
+
key: 'container',
|
|
98
|
+
patternType: 'css',
|
|
99
|
+
returnType: 'text',
|
|
100
|
+
patterns: ['.product'],
|
|
101
|
+
meta: { isContainer: true },
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
key: 'name',
|
|
105
|
+
patternType: 'css',
|
|
106
|
+
returnType: 'text',
|
|
107
|
+
patterns: ['h2.woocommerce-loop-product__title'],
|
|
108
|
+
pipes: { trim: true },
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
key: 'price',
|
|
112
|
+
patternType: 'css',
|
|
113
|
+
returnType: 'text',
|
|
114
|
+
patterns: ['.price'],
|
|
115
|
+
pipes: { trim: true },
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
});
|
|
119
|
+
this.logger.log(`[products] found ${products.results.length} products (${Date.now() - startedAt}ms)`);
|
|
120
|
+
this.logger.debug(`[products] results: ${JSON.stringify(products.results, null, 2)}`);
|
|
121
|
+
return products;
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
this.logger.error(`[products] scrape failed after ${Date.now() - startedAt}ms`, err instanceof Error ? err.stack : String(err));
|
|
125
|
+
throw err;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async runCurrentPageExtract() {
|
|
129
|
+
this.logger.log('[products] extracting <h1> from current page (no navigation)');
|
|
130
|
+
try {
|
|
131
|
+
const title = await this.products.extract({ h1: 'h1' });
|
|
132
|
+
this.logger.log(`[products] current page title: "${title.h1}"`);
|
|
133
|
+
return title;
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
this.logger.error('[products] extract failed', err instanceof Error ? err.stack : String(err));
|
|
137
|
+
throw err;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
CrawlerService = CrawlerService_1 = __decorate([
|
|
142
|
+
(0, common_1.Injectable)(),
|
|
143
|
+
__param(0, (0, index_1.InjectPageController)('login', 'stealth')),
|
|
144
|
+
__param(1, (0, index_1.InjectPageController)('products', 'stealth')),
|
|
145
|
+
__metadata("design:paramtypes", [index_1.PageController,
|
|
146
|
+
index_1.PageController])
|
|
147
|
+
], CrawlerService);
|
|
148
|
+
let AppModule = class AppModule {
|
|
149
|
+
};
|
|
150
|
+
AppModule = __decorate([
|
|
151
|
+
(0, common_1.Module)({
|
|
152
|
+
imports: [
|
|
153
|
+
index_1.BrowserActionModule.forRoot({
|
|
154
|
+
name: 'stealth',
|
|
155
|
+
cloak: {
|
|
156
|
+
headless: process.env.HEADLESS !== 'false',
|
|
157
|
+
},
|
|
158
|
+
}),
|
|
159
|
+
index_1.BrowserActionModule.forFeature(['login', 'products'], 'stealth'),
|
|
160
|
+
],
|
|
161
|
+
providers: [CrawlerService],
|
|
162
|
+
})
|
|
163
|
+
], AppModule);
|
|
164
|
+
if (require.main === module) {
|
|
165
|
+
void (async () => {
|
|
166
|
+
const bootstrapLogger = new common_1.Logger('Bootstrap');
|
|
167
|
+
const app = await core_1.NestFactory.createApplicationContext(AppModule, {
|
|
168
|
+
logger: ['log', 'error', 'warn', 'debug', 'verbose'],
|
|
169
|
+
});
|
|
170
|
+
const crawler = app.get(CrawlerService);
|
|
171
|
+
try {
|
|
172
|
+
await crawler.run();
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
bootstrapLogger.error('Run aborted', err instanceof Error ? err.stack : String(err));
|
|
176
|
+
process.exitCode = 1;
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
await app.close();
|
|
180
|
+
}
|
|
181
|
+
})();
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=named-browser-example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"named-browser-example.js","sourceRoot":"","sources":["../../src/examples/named-browser-example.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -10,3 +10,8 @@ export * from './enums';
|
|
|
10
10
|
export * from './interfaces';
|
|
11
11
|
export * from './constants';
|
|
12
12
|
export * from './decorators';
|
|
13
|
+
export * from './common';
|
|
14
|
+
export * from './operators';
|
|
15
|
+
export * from './services/browser-holder';
|
|
16
|
+
export * from './services/page-session';
|
|
17
|
+
export * from './services/page-controller';
|
package/dist/index.js
CHANGED
|
@@ -26,4 +26,9 @@ __exportStar(require("./enums"), exports);
|
|
|
26
26
|
__exportStar(require("./interfaces"), exports);
|
|
27
27
|
__exportStar(require("./constants"), exports);
|
|
28
28
|
__exportStar(require("./decorators"), exports);
|
|
29
|
+
__exportStar(require("./common"), exports);
|
|
30
|
+
__exportStar(require("./operators"), exports);
|
|
31
|
+
__exportStar(require("./services/browser-holder"), exports);
|
|
32
|
+
__exportStar(require("./services/page-session"), exports);
|
|
33
|
+
__exportStar(require("./services/page-controller"), exports);
|
|
29
34
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AACA,0DAAwC;AAGxC,kEAAgD;AAChD,qEAAmD;AACnD,0DAAwC;AACxC,4DAA0C;AAC1C,+DAA6C;AAG7C,oEAAkD;AAGlD,0CAAwB;AAGxB,0CAAwB;AAGxB,+CAA6B;AAG7B,8CAA4B;AAG5B,+CAA6B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AACA,0DAAwC;AAGxC,kEAAgD;AAChD,qEAAmD;AACnD,0DAAwC;AACxC,4DAA0C;AAC1C,+DAA6C;AAG7C,oEAAkD;AAGlD,0CAAwB;AAGxB,0CAAwB;AAGxB,+CAA6B;AAG7B,8CAA4B;AAG5B,+CAA6B;AAG7B,2CAAyB;AAGzB,8CAA4B;AAG5B,4DAA0C;AAC1C,0DAAwC;AACxC,6DAA2C"}
|
|
@@ -19,6 +19,9 @@ export interface RemoteOptions {
|
|
|
19
19
|
retryMax?: number;
|
|
20
20
|
retryDelay?: number;
|
|
21
21
|
}
|
|
22
|
+
export interface HealthCheckOptions {
|
|
23
|
+
intervalMs: number;
|
|
24
|
+
}
|
|
22
25
|
export interface BrowserActionOptions {
|
|
23
26
|
launchOptions?: LaunchOptions;
|
|
24
27
|
cloak?: CloakOptions;
|
|
@@ -31,4 +34,7 @@ export interface BrowserActionOptions {
|
|
|
31
34
|
cookies?: CookieOptions;
|
|
32
35
|
customPipes?: Record<string, new (...args: unknown[]) => CleansingPipe>;
|
|
33
36
|
lazyInit?: boolean;
|
|
37
|
+
name?: string;
|
|
38
|
+
healthCheck?: HealthCheckOptions;
|
|
39
|
+
maxPages?: number;
|
|
34
40
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Page, ScreenshotOptions, PDFOptions } from 'puppeteer-core';
|
|
2
|
+
import { LoggerWithLevel } from '../utils/logger.util';
|
|
3
|
+
import type { TlsFingerprint } from '../interfaces/tls-fingerprint';
|
|
4
|
+
export declare class CaptureOperator {
|
|
5
|
+
private readonly logger;
|
|
6
|
+
constructor(logger: LoggerWithLevel);
|
|
7
|
+
screenshot(page: Page, path: string, options?: ScreenshotOptions): Promise<Buffer>;
|
|
8
|
+
pdf(page: Page, path: string, options?: PDFOptions): Promise<Buffer>;
|
|
9
|
+
tlsFingerprint(page: Page, path: string): Promise<TlsFingerprint>;
|
|
10
|
+
private buildTlsFingerprint;
|
|
11
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CaptureOperator = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
class CaptureOperator {
|
|
7
|
+
logger;
|
|
8
|
+
constructor(logger) {
|
|
9
|
+
this.logger = logger;
|
|
10
|
+
}
|
|
11
|
+
async screenshot(page, path, options) {
|
|
12
|
+
const result = await page.screenshot({ path, ...options });
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
async pdf(page, path, options) {
|
|
16
|
+
const pdf = await page.pdf({ path, ...options });
|
|
17
|
+
return Buffer.from(pdf);
|
|
18
|
+
}
|
|
19
|
+
async tlsFingerprint(page, path) {
|
|
20
|
+
const rawJson = await page.evaluate(() => document.body.innerText);
|
|
21
|
+
const data = JSON.parse(rawJson);
|
|
22
|
+
const fingerprint = this.buildTlsFingerprint(data);
|
|
23
|
+
await fs_1.promises.mkdir((0, path_1.dirname)(path), { recursive: true });
|
|
24
|
+
await fs_1.promises.writeFile(path, JSON.stringify(fingerprint, null, 2), 'utf-8');
|
|
25
|
+
this.logger.log(`Saved TLS fingerprint to ${path}`);
|
|
26
|
+
return fingerprint;
|
|
27
|
+
}
|
|
28
|
+
buildTlsFingerprint(data) {
|
|
29
|
+
const tls = (data.tls ?? {});
|
|
30
|
+
const http2 = (data.http2 ?? {});
|
|
31
|
+
const extensions = Array.isArray(tls.extensions)
|
|
32
|
+
? tls.extensions
|
|
33
|
+
: [];
|
|
34
|
+
const sentFrames = Array.isArray(http2.sent_frames)
|
|
35
|
+
? http2.sent_frames
|
|
36
|
+
: [];
|
|
37
|
+
const headersFrame = sentFrames.find((frame) => frame.frame_type === 'HEADERS');
|
|
38
|
+
return {
|
|
39
|
+
capturedAt: new Date().toISOString(),
|
|
40
|
+
ip: data.ip ?? '',
|
|
41
|
+
httpVersion: data.http_version ?? '',
|
|
42
|
+
method: data.method ?? '',
|
|
43
|
+
userAgent: data.user_agent ?? '',
|
|
44
|
+
ja3: tls.ja3 ?? '',
|
|
45
|
+
ja3Hash: tls.ja3_hash ?? '',
|
|
46
|
+
ja4: tls.ja4 ?? '',
|
|
47
|
+
ja4_r: tls.ja4_r,
|
|
48
|
+
peetprint: tls.peetprint ?? '',
|
|
49
|
+
peetprintHash: tls.peetprint_hash ?? '',
|
|
50
|
+
ciphers: Array.isArray(tls.ciphers) ? tls.ciphers : [],
|
|
51
|
+
tlsExtensions: extensions.map((ext) => String(ext.name)),
|
|
52
|
+
akamaiFingerprint: http2.akamai_fingerprint ?? '',
|
|
53
|
+
akamaiFingerprintHash: http2.akamai_fingerprint_hash ?? '',
|
|
54
|
+
headers: Array.isArray(headersFrame?.headers)
|
|
55
|
+
? headersFrame.headers
|
|
56
|
+
: [],
|
|
57
|
+
raw: data,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.CaptureOperator = CaptureOperator;
|
|
62
|
+
//# sourceMappingURL=capture.operator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.operator.js","sourceRoot":"","sources":["../../src/operators/capture.operator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Page } from 'puppeteer-core';
|
|
2
|
+
import { PipeEngine } from '../pipes/pipe-engine';
|
|
3
|
+
import { LoggerWithLevel } from '../utils/logger.util';
|
|
4
|
+
import { ExtractionOperator } from './extraction.operator';
|
|
5
|
+
import type { ContainerDescriptor, ContainerScrapeResult, PaginationDescriptor, PaginationResult } from '../interfaces/types';
|
|
6
|
+
export declare class ContainerOperator {
|
|
7
|
+
private readonly extraction;
|
|
8
|
+
private readonly pipeEngine;
|
|
9
|
+
private readonly logger;
|
|
10
|
+
constructor(extraction: ExtractionOperator, pipeEngine: PipeEngine, logger: LoggerWithLevel);
|
|
11
|
+
executeContainerExtraction<T = Record<string, unknown>>(page: Page, descriptor: ContainerDescriptor<T>, currentPage?: number): Promise<ContainerScrapeResult<T>>;
|
|
12
|
+
resolvePagination(page: Page, descriptor: PaginationDescriptor, currentPage?: number): Promise<PaginationResult>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContainerOperator = void 0;
|
|
4
|
+
class ContainerOperator {
|
|
5
|
+
extraction;
|
|
6
|
+
pipeEngine;
|
|
7
|
+
logger;
|
|
8
|
+
constructor(extraction, pipeEngine, logger) {
|
|
9
|
+
this.extraction = extraction;
|
|
10
|
+
this.pipeEngine = pipeEngine;
|
|
11
|
+
this.logger = logger;
|
|
12
|
+
}
|
|
13
|
+
async executeContainerExtraction(page, descriptor, currentPage = 1) {
|
|
14
|
+
const rawItems = await page.evaluate((containerSel, fieldDefs) => {
|
|
15
|
+
const isXPath = (s) => s.trim().startsWith('//') ||
|
|
16
|
+
s.trim().startsWith('(') ||
|
|
17
|
+
s.trim().startsWith('./');
|
|
18
|
+
const getContainerNodes = (sel) => {
|
|
19
|
+
if (isXPath(sel)) {
|
|
20
|
+
const res = document.evaluate(sel, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
|
21
|
+
const nodes = [];
|
|
22
|
+
for (let i = 0; i < res.snapshotLength; i++)
|
|
23
|
+
nodes.push(res.snapshotItem(i));
|
|
24
|
+
return nodes;
|
|
25
|
+
}
|
|
26
|
+
return Array.from(document.querySelectorAll(sel));
|
|
27
|
+
};
|
|
28
|
+
const extractOne = (sel, root, attr, returnType) => {
|
|
29
|
+
let node = null;
|
|
30
|
+
if (isXPath(sel)) {
|
|
31
|
+
const res = document.evaluate(sel, root, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
|
|
32
|
+
node = res.singleNodeValue;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
node = root.querySelector(sel);
|
|
36
|
+
}
|
|
37
|
+
if (!node)
|
|
38
|
+
return '';
|
|
39
|
+
if (attr)
|
|
40
|
+
return node.getAttribute?.(attr) ?? '';
|
|
41
|
+
if (returnType === 'html')
|
|
42
|
+
return node.innerHTML ?? '';
|
|
43
|
+
return node.textContent?.trim() ?? '';
|
|
44
|
+
};
|
|
45
|
+
const extractMany = (sel, root, attr, returnType) => {
|
|
46
|
+
let nodes = [];
|
|
47
|
+
if (isXPath(sel)) {
|
|
48
|
+
const res = document.evaluate(sel, root, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
|
49
|
+
for (let i = 0; i < res.snapshotLength; i++)
|
|
50
|
+
nodes.push(res.snapshotItem(i));
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
nodes = Array.from(root.querySelectorAll(sel));
|
|
54
|
+
}
|
|
55
|
+
return nodes.map((n) => {
|
|
56
|
+
if (attr)
|
|
57
|
+
return n.getAttribute?.(attr) ?? '';
|
|
58
|
+
if (returnType === 'html')
|
|
59
|
+
return n.innerHTML ?? '';
|
|
60
|
+
return n.textContent?.trim() ?? '';
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
const extractField = (root, fd) => {
|
|
64
|
+
const selectors = [fd.selector, ...(fd.fallback ?? [])];
|
|
65
|
+
for (const sel of selectors) {
|
|
66
|
+
const val = fd.multiple
|
|
67
|
+
? extractMany(sel, root, fd.attribute, fd.returnType)
|
|
68
|
+
: extractOne(sel, root, fd.attribute, fd.returnType);
|
|
69
|
+
if (Array.isArray(val) ? val.length > 0 : val !== '')
|
|
70
|
+
return val;
|
|
71
|
+
}
|
|
72
|
+
return fd.multiple ? [] : '';
|
|
73
|
+
};
|
|
74
|
+
return getContainerNodes(containerSel).map((node) => {
|
|
75
|
+
const item = {};
|
|
76
|
+
for (const [key, fd] of Object.entries(fieldDefs))
|
|
77
|
+
item[key] = extractField(node, fd);
|
|
78
|
+
return item;
|
|
79
|
+
});
|
|
80
|
+
}, descriptor.container, descriptor.fields);
|
|
81
|
+
const items = rawItems;
|
|
82
|
+
let pagination;
|
|
83
|
+
if (descriptor.pagination) {
|
|
84
|
+
pagination = await this.resolvePagination(page, descriptor.pagination, currentPage);
|
|
85
|
+
}
|
|
86
|
+
return { items, pagination };
|
|
87
|
+
}
|
|
88
|
+
async resolvePagination(page, descriptor, currentPage = 1) {
|
|
89
|
+
currentPage = Math.max(1, currentPage);
|
|
90
|
+
const rawPages = await page.evaluate((containerSel, linkSel, labelSel) => {
|
|
91
|
+
const getNode = (sel, root) => {
|
|
92
|
+
if (sel.trim().startsWith('//') ||
|
|
93
|
+
sel.trim().startsWith('(') ||
|
|
94
|
+
sel.trim().startsWith('./')) {
|
|
95
|
+
const res = document.evaluate(sel, root, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
|
|
96
|
+
return res.singleNodeValue;
|
|
97
|
+
}
|
|
98
|
+
return root.querySelector(sel);
|
|
99
|
+
};
|
|
100
|
+
const getNodes = (sel, root) => {
|
|
101
|
+
if (sel.trim().startsWith('//') ||
|
|
102
|
+
sel.trim().startsWith('(') ||
|
|
103
|
+
sel.trim().startsWith('./')) {
|
|
104
|
+
const res = document.evaluate(sel, root, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
|
105
|
+
const nodes = [];
|
|
106
|
+
for (let i = 0; i < res.snapshotLength; i++)
|
|
107
|
+
nodes.push(res.snapshotItem(i));
|
|
108
|
+
return nodes;
|
|
109
|
+
}
|
|
110
|
+
return Array.from(root.querySelectorAll(sel));
|
|
111
|
+
};
|
|
112
|
+
const container = getNode(containerSel, document);
|
|
113
|
+
if (!container)
|
|
114
|
+
return [];
|
|
115
|
+
return getNodes(linkSel, container).map((el) => {
|
|
116
|
+
const isXPath = (s) => s.trim().startsWith('//') ||
|
|
117
|
+
s.trim().startsWith('(') ||
|
|
118
|
+
s.trim().startsWith('./');
|
|
119
|
+
const labelNodes = isXPath(labelSel)
|
|
120
|
+
? (() => {
|
|
121
|
+
const r = document.evaluate(labelSel, el, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
|
122
|
+
const ns = [];
|
|
123
|
+
for (let i = 0; i < r.snapshotLength; i++)
|
|
124
|
+
ns.push(r.snapshotItem(i));
|
|
125
|
+
return ns;
|
|
126
|
+
})()
|
|
127
|
+
: Array.from(el.querySelectorAll(labelSel));
|
|
128
|
+
const label = labelNodes.length > 0
|
|
129
|
+
? (labelNodes[0].textContent?.trim() ?? '')
|
|
130
|
+
: (el.textContent?.trim() ?? '');
|
|
131
|
+
return {
|
|
132
|
+
label,
|
|
133
|
+
url: el.getAttribute('href') ?? '',
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
}, descriptor.container, descriptor.linkSelector, descriptor.labelSelector);
|
|
137
|
+
const pages = rawPages.filter((p) => p.url);
|
|
138
|
+
const numericNext = pages
|
|
139
|
+
.filter((p) => !Number.isNaN(parseInt(p.label, 10)) &&
|
|
140
|
+
parseInt(p.label, 10) > currentPage)
|
|
141
|
+
.sort((a, b) => parseInt(a.label, 10) - parseInt(b.label, 10))[0];
|
|
142
|
+
const nextUrl = numericNext?.url ??
|
|
143
|
+
pages.find((p) => ['next', '>'].includes(p.label.toLowerCase()))?.url ??
|
|
144
|
+
null;
|
|
145
|
+
return { pages, nextUrl };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.ContainerOperator = ContainerOperator;
|
|
149
|
+
//# sourceMappingURL=container.operator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container.operator.js","sourceRoot":"","sources":["../../src/operators/container.operator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Page } from 'puppeteer-core';
|
|
2
|
+
import { PipeEngine } from '../pipes/pipe-engine';
|
|
3
|
+
import { LoggerWithLevel } from '../utils/logger.util';
|
|
4
|
+
import type { SelectorMap, ScrapeResult, PipeOptions } from '../interfaces/types';
|
|
5
|
+
import type { ActionTarget, ActionOptions } from '../interfaces/workflow-options';
|
|
6
|
+
export declare class ExtractionOperator {
|
|
7
|
+
private readonly pipeEngine;
|
|
8
|
+
private readonly logger;
|
|
9
|
+
constructor(pipeEngine: PipeEngine, logger: LoggerWithLevel);
|
|
10
|
+
parseSelector(raw: string): {
|
|
11
|
+
selector: string;
|
|
12
|
+
attribute?: string;
|
|
13
|
+
};
|
|
14
|
+
validateSelector(key: string, selector: string): void;
|
|
15
|
+
extractSingle(page: Page, url: string, selectors: SelectorMap, pipes?: PipeOptions): Promise<ScrapeResult>;
|
|
16
|
+
extractAllData(page: Page, target: ActionTarget, as?: ActionOptions['as'], attribute?: string): Promise<string[]>;
|
|
17
|
+
extractAllFromShadowRoot(page: Page, target: ActionTarget, as?: ActionOptions['as'], attribute?: string): Promise<string[]>;
|
|
18
|
+
extractData(page: Page, target: ActionTarget, as?: ActionOptions['as'], attribute?: string, debugLogMaxLength?: number): Promise<string>;
|
|
19
|
+
private describeTarget;
|
|
20
|
+
private findElement;
|
|
21
|
+
private findElementInShadowRoot;
|
|
22
|
+
}
|