import { CheerioCrawler } from '@crawlee/cheerio'; import { sleep } from '@crawlee/utils'; import { Actor } from 'apify'; const mainOptions = { exit: Actor.isAtHome(), storage: process.env.STORAGE_IMPLEMENTATION === 'LOCAL' ? new (await import('@apify/storage-local')).ApifyStorageLocal() : undefined, }; const LABELS = { TIMEOUT: 'TIMEOUT', TYPE_ERROR: 'TYPE_ERROR', ERROR_OPENING_PAGE: 'ERROR_OPENING_PAGE', POST_NAVIGATION_ERROR: 'POST_NAVIGATION_ERROR', }; // Pre Navigation errors snapshots will not be saved as we don't get the response in the context await Actor.main(async () => { const crawler = new CheerioCrawler({ requestHandlerTimeoutSecs: 2, maxRequestRetries: 0, statisticsOptions: { saveErrorSnapshots: true, }, async requestHandler({ $, request, log }) { const { userData: { label }, } = request; if (label === LABELS.TIMEOUT) { log.error('Timeout error'); await sleep(20_000); } if (label === LABELS.TYPE_ERROR) { log.error('TypeError: $(...).error is not a function'); $().error(); } else if (label === LABELS.ERROR_OPENING_PAGE) { log.error('Error opening page'); throw new Error('An error occurred while opening the page'); } }, postNavigationHooks: [ async ({ request, log }) => { const { userData: { label }, } = request; // Post navigation errors snapshots are not saved as we don't get the body in the context if (label === LABELS.POST_NAVIGATION_ERROR) { log.error('Post navigation error'); throw new Error('Unable to navigate to the requested post'); } }, ], }); await crawler.run( Object.values(LABELS).map((label) => ({ url: 'https://crawlee.dev', userData: { label }, uniqueKey: label })), ); }, mainOptions);