[英]What are the best practices to pass variable to outer scope while using Promise?
我正在使用 Cheerio 和 puppeteer 编写 Scraper 脚本。 在每个循环中,我想解析一个重定向的 url 字段。 使用 Promise 我可以控制台记录它,但将它插入元数据的最佳方法是什么?
我实际上也对控制流感到困惑。
(async function main() {
const browser = await puppeteer.launch({
headless: true,
});
const page = await browser.newPage();
await page.goto('https://www.example.com/?q=async+urls&s=s');
const content = await page.content();
const $ = cheerio.load(content);
var parsedResults = [];
const fetchRedirect = async (url) => {
try {
let response = await doRequest(url);
return response;
} catch (err) {
return false;
}
};
const videoBlocks = $('td[itemprop="subjectOf"]').first().each(function (i, element) {
const url = ($(this).find('a.title').attr('href'));
const fetchUrl = fetchRedirect(url);
// ** i can console log the redirected url **/
fetchUrl.then(url => console.log(url));
const title = ($(this).find('a.title').text());
var metadata = {
title
};
parsedResults.push(metadata);
});
function doRequest(url) {
return new Promise(function (resolve, reject) {
request(url, function (error, res, body) {
if (!error) {
resolve(getPathFromUrl(res.request.uri.href));
} else {
reject(error);
}
});
});
}
function getPathFromUrl(url) {
return url.split(/[?#]/)[0];
}
console.log(parsedResults);
await page.close()
await browser.close();
})();
//...............await!
const fetchUrl = await fetchRedirect(url);
// ** then instead that **/
// fetchUrl.then(url => console.log(url));
// just
console.log(fetchUrl)
const title = ($(this).find('a.title').text());
var metadata = {
title
};
parsedResults.push(metadata);
就我个人而言,我会 go 用于节点模块。 像这样的代码很难阅读,因为您在一个函数(main)中声明了多个函数。 是否应用 OOP 或函数式编程取决于您的偏好(第二种在 Node 环境中更受欢迎,但如果我要围绕特定实体创建功能,我更喜欢第一种)。 避免嵌套和抽象函数(您在其他函数中声明的函数)对于创建可重用和可读的代码至关重要。
这是一个工作原型(未经测试)。 它使 puppeteer 实例可重用。 该模块公开了三个方法:start、stop、 crawlWeb
'use strict'
var browser;
async function crawlWeb(options) {
// validate options and throw errors
if (!options.url) {
throw new Error('url is invalid');
}
if (!browser) {
throw new Error('puppeteer is not started');
}
const page = await browser.newPage();
await page.goto(optionsl.url);
const content = await page.content();
const $ = cheerio.load(content);
const metas = extracMetadata($);
for (let metadata of metas) {
// you can verify if site is valid
// you can use await
try {
await doRequest(metadata.url);
}
catch(err) {
// do something if not valid
}
}
return metas;
}
async function start(options) {
browser = await puppeteer.launch(options);
}
async function stop() {
if (!browser) {
throw new Error('puppeteer is not started');
}
await page.close()
await browser.close();
}
function extracMetadata($) {
const metas = [];
$('td[itemprop="subjectOf"]').first().each(function (i, element) {
const url = ($(this).find('a.title').attr('href'));
const title = ($(this).find('a.title').text());
var metadata = {
url,
title
};
metas.push(metadata);
});
return metas;
}
function doRequest(url) {
return new Promise(function (resolve, reject) {
request(url, function (error, res, body) {
if (!error) {
resolve(getPathFromUrl(res.request.uri.href));
} else {
reject(error);
}
});
});
}
function getPathFromUrl(url) {
return url.split(/[?#]/)[0];
}
module.exports = {
crawlWeb,
start,
stop
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.