You need to enable JavaScript to run this app. NestJS实现新闻爬虫时出现getaddrinfo ENOTFOUND错误如何解决?
优惠活动
大模型
产品
解决方案
定价
更多

NestJS实现新闻爬虫时出现getaddrinfo ENOTFOUND错误如何解决?

报错排查与解决步骤

getaddrinfo ENOTFOUND 错误本质是运行服务的机器无法把目标域名解析为对应IP地址,按优先级排查即可:

1. 基础网络连通性排查

  • 登录部署NestJS的服务器,执行ping livennov.ru,如果请求超时说明服务器网络限制无法访问目标站点
  • 执行nslookup livennov.ru测试DNS解析是否正常,如果没有返回对应IP,可更换公共DNS(114.114.114.114/8.8.8.8)后重试
  • 检查服务器出口防火墙、安全组规则,是否禁止访问境外站点,若有封禁规则可配置HTTP代理解决访问限制

2. 代码问题修复

你提供的代码本身存在多个会触发未捕获Promise异常的逻辑漏洞,修复后的完整代码如下:

import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { InjectRepository } from '@nestjs/typeorm';
import { TypeOrmCrudService } from '@nestjsx/crud-typeorm';
import { News } from './entity/news.entity';
import axios from 'axios';
import * as cheerio from 'cheerio';

@Injectable()
export class NewsService extends TypeOrmCrudService<News> {
    constructor(@InjectRepository(News) private readonly newsRepository) {
        super(newsRepository);
    }

    async fillNewsArray(): Promise<News[]> {
        const newsArray: News[] = []; // 初始化数组避免push报错
        // 封装请求方法加超时和异常捕获
        const getHTML = async (url) => {
            try {
                const { data } = await axios.get(url, { timeout: 10000 });
                return cheerio.load(data);
            } catch (err) {
                console.error(`请求${url}失败:`, err.message);
                throw err;
            }
        };

        try {
            const selector = await getHTML('https://livennov.ru/news/?PAGEN_2=1');
            const elements = selector('div.b-section-item__body').toArray();
            // 替换each+async的错误写法,用串行循环控制请求频率避免被封IP
            for (const element of elements) {
                const object = new News(); // 初始化实体类避免属性赋值报错
                const title = selector(element).find('h3.b-section-item__title').text().trim();
                const date = selector(element).find('div.b-meta-item').text().trim();
                const relativeUrl = selector(element).find('a').attr('href');
                if (!relativeUrl) continue; // 跳过无效数据
                const url = `https://livennov.ru${relativeUrl}`;
                const descSelector = await getHTML(url);
                descSelector('h2').remove();
                const imgRelativePath = descSelector('.content-full-width').find('img').attr('data-src');
                const imgUrl = imgRelativePath ? `https://livennov.ru${imgRelativePath}` : '';
                const descr = descSelector('div.b-news-detail-body').text().trim();

                object.headline = title;
                object.description = descr;
                object.imageUrl = imgUrl;
                object.originalUrl = url;
                object.dateTime = date;
                object.type = 'sports';
                newsArray.push(object);
                // 请求间隔1秒避免触发反爬
                await new Promise(resolve => setTimeout(resolve, 1000));
            }
            // 批量入库
            await this.newsRepository.save(newsArray);
            return newsArray;
        } catch (err) {
            console.error('爬虫执行失败:', err.message);
            throw err;
        }
    }

    // 调整为10分钟爬一次,10秒请求频率过高容易被封IP
    @Cron(CronExpression.EVERY_10_MINUTES)
    async handleCron() {
        // 捕获定时任务异常避免进程崩溃
        await this.fillNewsArray().catch(err => console.error('定时任务执行失败:', err));
    }
}

3. 特殊场景兜底

如果确认网络正常但仍存在解析失败问题,可给axios配置代理参数:

await axios.get(url, {
  timeout: 10000,
  proxy: {
    host: '代理IP地址',
    port: 代理端口
  }
})

Node版本低于18的环境可额外安装dnscache依赖开启全局DNS缓存,减少重复解析失败概率。

内容的提问来源于stack exchange,提问作者brothergod1

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 16:54:04