我有以下场景:
- 我的爬虫需要登录,所以我总是需要先点击一个登录页面
- 然后我有一个包含 30 个 url 的列表,我可以根据需要异步抓取这些 url
- 然后在最后,当所有这 30 个 url 都被抓取后,我需要点击最后一个单独的 url 以将 30 个 URL 抓取的结果放入 firebase 数据库并进行一些其他更改(例如地址的地理查找等等)
目前我有一个请求队列中的所有 30 个 url(通过 Apify 网络界面),我正在尝试查看它们何时全部完成。
但显然它们都是异步运行的,因此数据永远不可靠
const queue = await Apify.openRequestQueue();
let pendingRequestCount = await queue.getInfo();
我需要将最后一个 URL 分开的原因有两个:
- 最明显的原因是我需要确定我有 在我将所有内容发送到 DB 之前所有 30 次抓取的结果
- 这 30 个 URL 都不允许我进行 Ajax/Fetch 调用,这 我需要发送到 Firebase 并进行地址的地理查找
编辑:根据@Lukáš Křivka 的回答进行了尝试。 while 循环中的 handledRequestCount 达到最大值 2,而不是 4 ...,Puppeteer 正常结束。我将“return”放在 while 循环中,否则请求永远不会完成(当然)。
在我当前的测试设置中,我有 4 个要抓取的 url(在 Puppeteer Scraper(在 Apify.com 上)的 Start URLS 输入字段中和此代码:
let title = "";
const queue = await Apify.openRequestQueue();
let {handledRequestCount} = await queue.getInfo();
while (handledRequestCount < 4){
await new Promise((resolve) => setTimeout(resolve, 2000)) // wait for 2 secs
handledRequestCount = await queue.getInfo().then((info) => info.handledRequestCount);
console.log(`Curently handled here: ${handledRequestCount} --- waiting`) // this goes max to '2'
title = await page.evaluate(()=>{ return $('h1').text()});
return {title};
}
log.info("Here I want to add another URL to the queue where I can do ajax stuff to save results from above runs to firebase db");
title = await page.evaluate(()=>{ return $('h1').text()});
return {title};
最佳答案
我需要查看您的代码才能完全正确地回答,但这有解决方案。
只需使用 Apify.PuppeteerCrawler对于 30 个 URL。然后使用 await crawler.run()
运行爬虫。
之后,您可以简单地通过以下方式从默认数据集中加载数据
const dataset = await Apify.openDataset();
const data = await dataset.getdata().then((response) => response.items);
无论对数据做什么,您甚至可以创建新的 Apify.PuppeteerCrawler
来抓取最后一个 URL 并使用数据。
不过,如果您使用的是 Web Scraper,那就有点复杂了。您可以:
1) 为 Firebase 上传创建一个单独的 actor,并从 Web Scraper 向其传递一个 webhook 以从中加载数据。如果您查看 Apify store ,我们已经有了一个 Firestore uploader 。
2) 添加一个逻辑,该逻辑将像您所做的那样轮询 requestQueue
,并且仅当所有请求都已处理时,您才继续。您可以创建某种等待的循环。例如
const queue = await Apify.openRequestQueue();
let { handledRequestCount } = await queue.getInfo();
while (handledRequestCount < 30) {
console.log(`Curently handled: ${handledRequestCount } --- waiting`)
await new Promise((resolve) => setTimeout(resolve, 2000)) // wait for 2 secs
handledRequestCount = await queue.getInfo().then((info) => info.handledRequestCount);
}
// Do your Firebase stuff
关于javascript - 完成所有操作后再进行一次抓取的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57472856/