You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 00:45:40