我已经使用axios.all
方法建立了一个后端路由,该方法从三个不同的站点提取数据,然后将它们抓取到Axios .then
块中。我正在使用Cheerio的.each
循环方法来抓取匹配的文章标题,图像链接和故事链接,但是在.each
循环的每次运行中,我还想将每篇文章的详细信息存储到MongoDB中数据库。是否有一种方法可以等待.each
循环中的那些查询,或者以某种方式将三个.each
循环包装在promise中,以便所有抓取和数据库查询都在触发res.send('Scrape complete')
之前发生? / p>
我尝试将另一个.then
方法链接到第一个.then
方法,但是在完成.each
循环中的所有异步查询之前,它仍然继续进行下去。我还尝试将三个.each
方法包装在Promise
类中。
这是当前的后台文章抓取功能
router.get('/articleScrape', (req, res) => {
axios
.all([
axios.get('https://thespool.net/'),
axios.get('https://www.overthinkingit.com/'),
axios.get('https://filmschoolrejects.com/'),
])
.then(
axios.spread((spoolRes, overthinkingRes, filmSchoolRes) => {
const spool = cheerio.load(spoolRes.data);
const over = cheerio.load(overthinkingRes.data);
const fsr = cheerio.load(filmSchoolRes.data);
spool('div .hover__handler').each(function (i, element) {
const result = {};
result.title = spool(this)
.children('header')
.children('a')
.children('h1')
.text()
.replace('\n', '');
result.siteURL = 'thespool.net';
result.linkURL = spool(this)
.children('header')
.children('a')
.attr('href');
result.imgURL = spool(this)
.children('aside')
.children('img')
.attr('src');
db.Article.findOne({ title: result.title }).then((searchedArticle) => {
if (!searchedArticle) {
db.Article.create(result)
.then((dbArticle) => {
console.log(dbArticle);
})
.catch((err) => {
console.log(err);
});
}
});
});
over('.post').each(function (i, element) {
const result = {};
result.title = over(this)
.find('h2')
.text();
result.siteURL = 'overthinkingit.com';
result.linkURL = over(this)
.find('.entry--archive__title-link')
.attr('href');
result.imgURL = over(this)
.find('img')
.attr('src');
db.Article.findOne({ title: result.title }).then((searchedArticle) => {
if (!searchedArticle) {
db.Article.create(result)
.then((dbArticle) => {
console.log(dbArticle);
})
.catch((err) => {
console.log(err);
});
}
});
});
fsr('article').each(function (i, element) {
const result = {};
result.title = fsr(this)
.find('h3')
.text();
result.siteURL = 'filmschoolrejects.com';
result.linkURL = fsr(this)
.find('h3')
.children('a')
.attr('href');
result.imgURL = fsr(this)
.find('img')
.attr('data-src');
db.Article.findOne({ title: result.title }).then((searchedArticle) => {
if (!searchedArticle) {
db.Article.create(result)
.then((dbArticle) => {
console.log(dbArticle);
})
.catch((err) => {
console.log(err);
});
}
});
});
res.send('Scrape complete');
}),
);
});
我想确保在我第二次调用数据库以检索刚创建的文章之前完成此刮擦,这是通过第二条路线进行的:
router.get('/articles', (req, res) => {
db.Article.find({})
.then((dbArticles) => {
res.json(dbArticles);
})
.catch((err) => {
res.json(err);
});
});
最后,这是前端在页面加载时的调用顺序:
axios.get('/data/articleScrape').then(async (response) => {
console.log(response);
getArticles();
});
function getArticles() {
axios.get('/data/articles').then((response) => {
console.log(response.data);
});
}
我想要的是确保刮擦已完全完成,以便当我运行第二次调用以从数据库中获取文章时,它们就在那里了。我知道问题出在.each
循环中发生的异步调用中,但是我似乎找不到完美的解决方案。有帮助吗?