@crawlee/basic 4.0.0-beta.169 → 4.0.0-beta.170
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/internals/basic-crawler.js +11 -10
- package/package.json +7 -7
|
@@ -201,7 +201,7 @@ export class BasicCrawler {
|
|
|
201
201
|
#maxCrawlDepth;
|
|
202
202
|
#maxRequestsPerCrawl;
|
|
203
203
|
get handledRequestsCount() {
|
|
204
|
-
return this.statistics.state.
|
|
204
|
+
return this.statistics.state.requestsSucceeded + this.statistics.state.requestsFailed;
|
|
205
205
|
}
|
|
206
206
|
#statusMessageLoggingInterval;
|
|
207
207
|
#statusMessageCallback;
|
|
@@ -447,8 +447,9 @@ export class BasicCrawler {
|
|
|
447
447
|
}
|
|
448
448
|
// Started here, rather than in `handleRequest`, so that a failure during context pipeline
|
|
449
449
|
// initialization (e.g. a browser page timing out before the request handler ever runs) is
|
|
450
|
-
// still accounted for by `
|
|
451
|
-
|
|
450
|
+
// still accounted for by `recordRequestFailure` below - which is a no-op without a
|
|
451
|
+
// matching `recordRequestStart`.
|
|
452
|
+
this.statistics.recordRequestStart(request.id || request.uniqueKey);
|
|
452
453
|
const crawlingContext = { request };
|
|
453
454
|
try {
|
|
454
455
|
// The transaction spans the whole pipeline call, covering the navigation hooks
|
|
@@ -465,7 +466,7 @@ export class BasicCrawler {
|
|
|
465
466
|
// ContextPipelineInterruptedError means the request was intentionally skipped
|
|
466
467
|
// (e.g., doesn't match enqueue strategy after redirect). Just return gracefully.
|
|
467
468
|
if (error instanceof ContextPipelineInterruptedError) {
|
|
468
|
-
this.statistics.
|
|
469
|
+
this.statistics.discardRequestRecord(request.id || request.uniqueKey);
|
|
469
470
|
await this.timeoutAndRetry(async () => this.requestManager?.markRequestAsHandled(request), this.internalTimeoutMillis, `Marking request ${crawlingContext.request.url} (${crawlingContext.request.id}) as handled timed out after ${this.internalTimeoutMillis / 1e3} seconds.`);
|
|
470
471
|
return;
|
|
471
472
|
}
|
|
@@ -762,7 +763,7 @@ export class BasicCrawler {
|
|
|
762
763
|
}
|
|
763
764
|
else {
|
|
764
765
|
const total = await this.requestManager?.getTotalCount();
|
|
765
|
-
message = `Crawled ${this.statistics.state.
|
|
766
|
+
message = `Crawled ${this.statistics.state.requestsSucceeded}${total ? `/${total}` : ''} pages, ${this.statistics.state.requestsFailed} failed requests, desired concurrency ${this.concurrencySystem?.desiredConcurrency ?? 0}.`;
|
|
766
767
|
}
|
|
767
768
|
if (this.#statusMessageCallback) {
|
|
768
769
|
await this.#statusMessageCallback({
|
|
@@ -872,7 +873,7 @@ export class BasicCrawler {
|
|
|
872
873
|
eventManager.off(EventType.ABORTING, boundPauseOnMigration);
|
|
873
874
|
const finalStats = this.statistics.calculate();
|
|
874
875
|
stats = {
|
|
875
|
-
|
|
876
|
+
requestsSucceeded: this.statistics.state.requestsSucceeded,
|
|
876
877
|
requestsFailed: this.statistics.state.requestsFailed,
|
|
877
878
|
retryHistogram: this.statistics.requestRetryHistogram,
|
|
878
879
|
...finalStats,
|
|
@@ -881,7 +882,7 @@ export class BasicCrawler {
|
|
|
881
882
|
// A crawl that did nothing while the manager holds only handled requests is a mistake whoever
|
|
882
883
|
// handled them - this run, another crawler on the same queue, or a previous process. Starting
|
|
883
884
|
// against handled requests is not: that is what resuming a crawl looks like.
|
|
884
|
-
if (stats.
|
|
885
|
+
if (stats.requestsSucceeded + stats.requestsFailed === 0) {
|
|
885
886
|
// Never let the diagnostic itself break the run.
|
|
886
887
|
const alreadyHandled = (await this.requestManager?.getHandledCount().catch(() => 0)) ?? 0;
|
|
887
888
|
if (alreadyHandled > 0) {
|
|
@@ -914,7 +915,7 @@ export class BasicCrawler {
|
|
|
914
915
|
finished = true;
|
|
915
916
|
}
|
|
916
917
|
periodicLogger.stop();
|
|
917
|
-
this.setStatusMessage(`Finished! Total ${this.statistics.state.
|
|
918
|
+
this.setStatusMessage(`Finished! Total ${this.statistics.state.requestsSucceeded + this.statistics.state.requestsFailed} requests: ${this.statistics.state.requestsSucceeded} succeeded, ${this.statistics.state.requestsFailed} failed.`, { isStatusMessageTerminal: true, level: 'INFO' });
|
|
918
919
|
await run.finish();
|
|
919
920
|
await this.#concurrencySystem.ifOwned((system) => system.stop());
|
|
920
921
|
this.#hasFinishedBefore = true;
|
|
@@ -1534,7 +1535,7 @@ export class BasicCrawler {
|
|
|
1534
1535
|
await transaction?.commit();
|
|
1535
1536
|
await this.timeoutAndRetry(async () => requestSource.markRequestAsHandled(request), this.internalTimeoutMillis, `Marking request ${request.url} (${request.id}) as handled timed out after ${this.internalTimeoutMillis / 1e3} seconds.`);
|
|
1536
1537
|
isRequestLocked = false; // markRequestAsHandled succeeded and unlocked the request
|
|
1537
|
-
this.statistics.
|
|
1538
|
+
this.statistics.recordRequestSuccess(statisticsId, request.retryCount);
|
|
1538
1539
|
// reclaim session if request finishes successfully
|
|
1539
1540
|
request.state = RequestState.DONE;
|
|
1540
1541
|
crawlingContext.session.markGood();
|
|
@@ -1704,7 +1705,7 @@ export class BasicCrawler {
|
|
|
1704
1705
|
// or failed more than retryCount times and will not be retried anymore.
|
|
1705
1706
|
// Mark the request as failed and do not retry.
|
|
1706
1707
|
await source.markRequestAsHandled(request);
|
|
1707
|
-
this.statistics.
|
|
1708
|
+
this.statistics.recordRequestFailure(request.id || request.uniqueKey, request.retryCount);
|
|
1708
1709
|
await this.handleFailedRequestHandler(crawlingContext, error); // This function prints an error message.
|
|
1709
1710
|
}
|
|
1710
1711
|
async handleFailedRequestHandler(crawlingContext, error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crawlee/basic",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.170",
|
|
4
4
|
"description": "The scalable web crawling and scraping library for JavaScript/Node.js. Enables development of data extraction and web automation jobs (not only) with headless Chrome and Puppeteer.",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"@apify/datastructures": "^3.0.1",
|
|
43
43
|
"@apify/timeout": "^1.0.1",
|
|
44
44
|
"@apify/utilities": "^3.0.1",
|
|
45
|
-
"@crawlee/core": "4.0.0-beta.
|
|
46
|
-
"@crawlee/http-client": "4.0.0-beta.
|
|
47
|
-
"@crawlee/types": "4.0.0-beta.
|
|
48
|
-
"@crawlee/utils": "4.0.0-beta.
|
|
45
|
+
"@crawlee/core": "4.0.0-beta.170",
|
|
46
|
+
"@crawlee/http-client": "4.0.0-beta.170",
|
|
47
|
+
"@crawlee/types": "4.0.0-beta.170",
|
|
48
|
+
"@crawlee/utils": "4.0.0-beta.170",
|
|
49
49
|
"csv-stringify": "^6.5.2",
|
|
50
50
|
"tldts": "^7.0.6",
|
|
51
51
|
"tslib": "^2.8.1",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"zod": "^4.5.4"
|
|
54
54
|
},
|
|
55
55
|
"optionalDependencies": {
|
|
56
|
-
"@crawlee/impit-client": "4.0.0-beta.
|
|
56
|
+
"@crawlee/impit-client": "4.0.0-beta.170"
|
|
57
57
|
},
|
|
58
58
|
"lerna": {
|
|
59
59
|
"command": {
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "86e1c891da983125e9e18f1a2327fbcf5e0f5fc2"
|
|
66
66
|
}
|