Node.js+MongoDB爬取网页数据无法存入数据库求助
Node.js爬虫无法将数据写入MongoDB问题
我正在使用Node.js结合MongoDB爬取网站数据,但无法将数据存入数据库。目前我能将爬取到的数据保存到数组bdata中,也能通过GET请求在localhost上展示这些数据,却无法写入MongoDB。以下是我的代码及Schema:
主代码
const axios = require('axios'); const cheerio = require('cheerio'); const express = require('express'); const port = 4000; const app = express(); const bodyParser = require('body-parser'); const mongoose = require("mongoose"); const Phones = require('./models/phones'); mongoose.Promise = global.Promise; mongoose.connect("mongodb://0.0.0.0:27017/testDatabase"); app.set('view engine', 'ejs'); app.use(express.json()) app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.urlencoded({ extended: false })); const url = 'https://scrapewebsite.com'; const bdata = []; async function scrapeSite(url) { try { const response = await axios.get(url); const $ = cheerio.load(response.data); const phones = $('.product-card'); // loop through products phones.each((i, phone) => { if ($(phone).find("ins span.woocommerce-Price-amount.amount")) { price = $(phone).find("ins span.woocommerce-Price-amount.amount").text(); } else if ($(phone).find(".price.font-bold.text-lg.md:text-xl.text-black")) { price = $(phone).find(".price.font-bold.text-lg.md:text-xl.text-black").text(); } article_name = $(phone).find(".woocommerce-loop-product__title").text(); link = $(phone).find("a").attr("href"); bdata.push({ "article": article_name, "link": link, "price": price }); }); //console.log(bdata); return; // iterate through all pages const hasNext = $(".next").text(); if (hasNext.length > 0) { next_page = $(".next").attr('href'); scrapeSite(next_page); } console.log(next_page); } catch (error) { console.error(error); } } scrapeSite(url); app.get('/', (req, res) => { res.render('index', { bdata: bdata }); }); app.listen(port, () => console.log('Example app listening on port ' + port));
Schema文件(./models/phones.js)
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const PhonesSchema = new Schema({ article: String, link: String, price: String }); module.exports = mongoose.model('Phones', PhonesSchema);
解决方法
1. 删除提前终止函数的return语句
原代码中scrapeSite函数在处理完当前页面数据后直接执行return,导致后续翻页逻辑和数据入库代码完全无法运行。直接删除这行:
// return; // 移除该行
2. 添加MongoDB数据写入逻辑
利用Mongoose的insertMany()方法,将收集到的bdata数组写入数据库。可以选择每爬完一页就写入,或者所有页面爬取完成后统一写入:
方案一:每爬完一页写入一次
在phones.each循环结束后,新增写入代码:
// 写入当前页新增的数据到数据库 await Phones.insertMany(bdata.slice(-phones.length));
方案二:所有页面爬完后统一写入
调整递归逻辑为异步递归,确保所有页面爬取完成后执行批量写入:
async function scrapeSite(url) { try { const response = await axios.get(url); const $ = cheerio.load(response.data); const phones = $('.product-card'); phones.each((i, phone) => { // 修复数据提取判断逻辑 let price = ''; if ($(phone).find("ins span.woocommerce-Price-amount.amount").length) { price = $(phone).find("ins span.woocommerce-Price-amount.amount").text().trim(); } else if ($(phone).find(".price.font-bold.text-lg.md:text-xl.text-black").length) { price = $(phone).find(".price.font-bold.text-lg.md:text-xl.text-black").text().trim(); } const article_name = $(phone).find(".woocommerce-loop-product__title").text().trim(); const link = $(phone).find("a").attr("href"); // 过滤空数据 if (article_name && link) { bdata.push({ "article": article_name, "link": link, "price": price }); } }); // 处理翻页,改用元素存在性判断更可靠 const hasNext = $(".next").length; if (hasNext) { const next_page = $(".next").attr('href'); await scrapeSite(next_page); // 异步递归,等待下一页爬取完成 } else { // 所有页面爬取完成,批量写入数据库 await Phones.insertMany(bdata); console.log('所有数据已成功写入MongoDB'); } } catch (error) { console.error(error); } }
3. 修复数据提取的判断逻辑
原代码中if ($(phone).find(...))的判断永远为真,因为jQuery对象即使找不到元素也会返回对象,必须用.length判断元素是否存在,同时添加.trim()去除多余空格,用let/const声明变量避免全局污染。
4. 确认MongoDB连接状态
添加连接成功的回调,确保数据库连接正常:
mongoose.connect("mongodb://0.0.0.0:27017/testDatabase") .then(() => console.log('MongoDB连接成功')) .catch(err => console.error('MongoDB连接失败:', err));
内容的提问来源于stack exchange,提问作者Loren Meta
相关产品推荐
相关产品推荐

