1import { Actor, log } from 'apify';
2import Scrapeless from 'scrapeless-sdk-node';
3
4await Actor.init();
5
6enum AmazonActionEnum {
7 product = 'product',
8 seller = 'seller',
9 keywords = 'keywords',
10}
11
12interface Input {
13 apiKey: string;
14 action: AmazonActionEnum;
15 webhook: string;
16 productUrl: string;
17 sellerUrl: string;
18 keywords: string;
19 maxConcurrency: number
20 pages: number;
21 domain: string;
22}
23
24const {
25 apiKey = '',
26 action = AmazonActionEnum.keywords,
27 webhook = '',
28 keywords = 'iPhone 12',
29 domain = 'com',
30 pages = 3,
31 maxConcurrency = 10,
32 productUrl = 'https://www.amazon.com/dp/B0BQXHK363',
33 sellerUrl = 'https://www.amazon.com/dp/B0BQXHK363',
34} = await Actor.getInput<Input>() ?? {};
35
36const CONCURRENCY_LIMIT = pages < maxConcurrency ? pages : maxConcurrency;
37
38
39const scrapeless = new Scrapeless({ apiKey });
40
41function getScrapelessInput(currentPage = 1) {
42 const baseInput = { action };
43 if (action === AmazonActionEnum.seller) {
44 return { ...baseInput, url: sellerUrl };
45 }
46 if (action === AmazonActionEnum.product) {
47 return { ...baseInput, url: productUrl };
48 }
49
50 return { ...baseInput, keywords, page: currentPage.toString(), domain };
51}
52
53async function scraperFetch() {
54 const response = await scrapeless.scraper({
55 actor: 'scraper.amazon',
56 webhook,
57 input: getScrapelessInput(),
58 });
59 await Actor.pushData(response as object);
60}
61
62async function keywordsConcurrencyScraperFetch() {
63 const RequestQueue: (() => Promise<object>)[] = [];
64 for (let page = 1; page <= pages; page++) {
65 RequestQueue.push(() => {
66 return scrapeless.scraper({
67 actor: 'scraper.amazon',
68 webhook,
69 input: getScrapelessInput(page),
70 });
71 });
72 }
73
74 const successfulResults: object[] = [];
75 let currentIndex = 0;
76 async function worker() {
77 while (currentIndex < RequestQueue.length) {
78 try {
79 log.info(`[Current page number]: ${currentIndex + 1}`);
80 const result = await RequestQueue[currentIndex++]();
81 await Actor.pushData(result);
82 successfulResults.push(result);
83 } catch (error) {
84 log.error(`[Request failed]: ${error}`);
85 }
86 }
87 }
88
89 const workers = [];
90 for (let i = 1; i <= CONCURRENCY_LIMIT; i++) {
91 workers.push(worker());
92 }
93 await Promise.all(workers);
94 log.info(`[🎉 Successfully captured ${successfulResults.length} pages of data]`);
95 await Actor.setValue('OUTPUT', successfulResults);
96}
97
98if (action === AmazonActionEnum.keywords) {
99 await keywordsConcurrencyScraperFetch();
100} else {
101 await scraperFetch();
102}
103
104await Actor.exit();