javascript - 使用 promise-pool 和 puppeteer 创建一个持续增加的列表
问题描述
我需要使用 puppeteer 创建抓取工具,但是我在将项目添加到队列时遇到了一些问题
我得到了什么
const PromisePool = require("@supercharge/promise-pool");
const puppeteer = require("puppeteer");
const domain = process.argv[2];
let list = [];
list[0] = domain;
const run = async () => {
const { results, errors } = await PromisePool.for(list)
.withConcurrency(2)
.process(async (webpage) => {
links = [];
const getData = async () => {
return await page.evaluate(async () => {
return await new Promise((resolve) => {
resolve(Array.from(document.querySelectorAll("a")).map((anchor) => [anchor.href]));
});
});
};
links = await getData();
for (var link in links) {
var new_url = String(links[link]);
new_url = new_url.split("#")[0];
console.log("new url: " + new_url);
if (new_url.includes(domain)) {
if (new_url in list) {
console.log("Url already exists: " + new_url);
continue;
}
list[new_url] = new_url;
} else {
console.log("Url is external: " + new_url);
}
}
browser.close();
});
};
const mainFunction = async () => {
const result = await run();
return result;
};
(async () => {
console.log(await mainFunction());
console.log(list);
})();
问题在里面
links = [];
const getData = async () => {
return await page.evaluate(async () => {
return await new Promise((resolve) => {
resolve(Array.from(document.querySelectorAll("a")).map((anchor) => [anchor.href]));
});
});
};
links = await getData();
page.evaluate 是异步的,它不等待返回,此链接永远不会为下一个 PromisePool 进程更新。
我需要一种方法来等待响应返回,然后继续处理脚本的其余部分。
解决方案
您可以使用page.$$eval
单个await
.
page.$$eval(selector, pageFunction[, ...args])
它基本上是您想要实现的,因为该$$eval
方法“Array.from(document.querySelectorAll(selector))
在页面 [上下文] 内运行并将其作为第一个参数传递给pageFunction
.”。(文档)
例如:
const links = await page.$$eval('a', anchors => anchors.map(el => el.href));
推荐阅读
- javascript - 打开另存为对话框以指定下载位置
- api - Wiki.js GraphQL:创建页面示例
- vue.js - 使用 v-show 时组件会重新渲染?VueJS
- python - 为什么 Django 没有创建 DB 模型的 dateTime 字段?
- haskell - 从 GHCi 隐藏随机版本
- javascript - Mongoose find() 检查是否有任何值匹配
- c++ - 基于非类型参数的类模板重载?
- c++ - 如何使用迭代器或c ++中的任何其他方式遍历元组向量
- java - Spring Boot - 如何通过实现 BeforeAllCallback 的自定义扩展类设置或覆盖 application.yml 中定义的属性?
- python - 根据另一个数据框中的列填充一个数据框中的空值?