I have two async functions.
- each function launches a headless browser.
- scrapeHeader() function scrape data and save to JSON file.
- scrapeData() function read from JSON file written by scrapeHeaders and scrape data. and save it to a JSON file.
I am calling both functions in the main function. I expect both of these functions to run in sequential order. But when I run the main function both functions run in parallel and launch two headless browsers. Here is the code.
async function main() {
// extract headers.
console.log("scraping headers ... ");
await scrapeHeaders();
// scrape data.
console.log("scraping data ... ");
await scrapeData();
}
In my previous implementation, I was returning data from scrapeHeaders() function and passing it to scrapeData() function then the logic was working as expected.
I've read that async/await code runs sequentially.
But I think the engine is considering both functions independent and that's why it is running them in parallel. How to tell the engine to wait until the first function is executed completely?
what's the other way to solve the problem without passing data from the first function to the second function?
code of scrapeHeaders method.
export async function scrapeHeaders() {
const url = 'url';
const browser = await puppeteer.launch({
headless: false,
defaultViewport: null,
});
const page = await browser.newPage();
// change user agent.
await changeUserAgent(page);
await page.setCookie({
name: "flmdat",
value:
"value",
domain: "www.something.com",
path: "/",
});
// block resources.
// await blockResources(page);
await page.goto(url, { timeout: 0, waitUntil: "networkidle2" });
// getting number of projects available on site.
const someData = await page.evaluate(() => {
//browser logic
});
if (someData === 0) {
console.log("No data available");
return [];
}
const possiblePages = Math.ceil(someData / 25);
const maxPages = 400;
const pages = possiblePages > maxPages ? max pages : possiblePages;
console.log("pages to scrape: ", pages);
let totalHeaders: Header[] = [];
await waitForTimeout(10000);
for (let i = 0; i < pages; i++) {
console.log(`going to page ${i + 1}`);
if (i !== 0) {
// gets next url if not first page
const nextUrl = `${url}?&page=${i + 1}`;
try {
await page.goto(nextUrl, {
timeout: 60000, // wait for 1 minute
waitUntil: "networkidle2",
});
} catch (err) {
handleError(err, `error while going to ${nextUrl}`);
}
}
const headers = await page.evaluate(() => {
// browser logic
return headers
});
// writing headers to file.
const headers = rawHeaders.filter(
(header) => header !== undefined
) as Header[];
// saving headers of each page to total headers array.
totalHeaders.push(...headers);
// saving headers scraped at the moment to file.
fs.writeFileSync(
"headers.json",
JSON.stringify(totalHeaders)
);
console.log(`got ${headers.length} projects info from page ${i + 1}`);
// to not burden server.
}
console.log(`scraped ${totalHeaders.length} headers`);
await browser.close();
}
code of scrapeData() method
export async function scrapeData() {
const browser = await puppeteer.launch({
headless: false,
defaultViewport: null,
});
const page = await browser.newPage();
// changing user agent
await changeUserAgent(page);
await page.setCookie({
name: "name",
value:
"value",
domain: "www.something.com",
path: "/",
});
let headers: Header[] = [];
try {
headers = JSON.parse(
fs.readFileSync("headers.json", "utf-8")
);
} catch (err) {
throw new Error("error while reading headers file in Posts");
}
console.log("total headers to scrape: ", headers.length);
let posts: Info[] = [];
for (let i = 0; i < headers.length; i++) {
// scrape data from post
try {
const post: Info | null = await scrapePost(
headers[i],
page
);
// if post is not available.
if (post === null) {
console.log(`post with ${headers[i].url} is not available. skipping it...`);
continue;
}
if (post.url) {
// scrape data from company page
const info: postPage = await Info(
post.url,
page
);
posts.push({ ...post, ...info });
} else {
data.push(post);
}
} catch (err) {
handleError(err, `error while scraping post page url:${headers[i].url}`);
}
if ((i + 1) % 10 === 0) {
// saving data in file after every 10 posts.
fs.writeFileSync("posts.json", JSON.stringify(post));
console.log(`Scraped ${i + 1} posts`);
}
}
fs.writeFileSync("posts.json", JSON.stringify(posts));
console.log(`scraped ${posts.length} posts`);
await page.close();
await browser.close();
}