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

无法抓取网站最内层页面标题,Promise使用问题求助

问题根源

你的脚本只返回第一个标题就卡住,核心问题是Promise的resolve在循环里被提前触发,且未正确处理多异步请求的并发逻辑:

  1. getInnerLinks只创建了一个Promise,但循环中第一个请求完成就调用了resolve,Promise一旦进入resolved状态就不会再变更,剩余请求的结果根本没被收集,导致办公点链接只存了第一个页面的数据。
  2. FetchTitle同理,第一个请求拿到标题就直接resolve,后续请求完全没被处理,脚本输出第一个标题后就无后续逻辑,看起来像是"卡住"。
  3. 全局数组landing_page_links和inner_page_links会导致多次运行时数据污染,应该在函数内部声明。

修复后的代码

用util.promisify把callback风格的request转成Promise版本,配合Promise.all处理多异步请求:

const request = require('request');
const cheerio = require('cheerio');
const { promisify } = require('util');

// 把request转换为Promise版本,适配async/await
const requestPromise = promisify(request);

const link = 'https://egpostal.com/en/p/all';
const base_link = 'https://egpostal.com/en/';

const getLinks = async () => {
    const { html } = await requestPromise(link);
    const $ = cheerio.load(html);
    const landingPageLinks = [];
    $('.table tbody tr').each(function() {
        landingPageLinks.push(base_link + $(this).find("a").attr("href"));
    });
    return landingPageLinks;
};

const getInnerLinks = async (links) => {
    // 每个链接的请求包装成Promise,用Promise.all等待所有请求完成
    const linkPromises = links.map(async (url) => {
        const { html } = await requestPromise(url);
        const $ = cheerio.load(html);
        const innerLinks = [];
        $('.table tbody tr').each(function() {
            innerLinks.push(base_link + $(this).find("a").attr("href"));
        });
        return innerLinks;
    });
    // 把二维数组扁平化为一维数组,得到所有办公点链接
    const allInnerLinksArrays = await Promise.all(linkPromises);
    return allInnerLinksArrays.flat();
};

const fetchTitles = async (links) => {
    const titlePromises = links.map(async (url) => {
        const { html } = await requestPromise(url);
        const $ = cheerio.load(html);
        return $(".home-title > h2").eq(0).text().trim();
    });
    // 等待所有标题抓取完成,返回标题数组
    return Promise.all(titlePromises);
};

// 执行流程
getLinks()
    .then(landingLinks => getInnerLinks(landingLinks))
    .then(innerLinks => fetchTitles(innerLinks))
    .then(titles => {
        console.log('所有抓取到的标题:');
        titles.forEach((title, index) => {
            console.log(`${index + 1}. ${title}`);
        });
    })
    .catch(err => console.error('执行出错:', err));

关键改动说明
  • 用util.promisify转换request,配合async/await让异步逻辑更直观,避免callback嵌套。
  • 每个函数内部声明数组,彻底避免全局变量的数据污染问题。
  • 用Promise.all批量处理多异步请求,确保所有请求完成后再返回结果,不会提前触发resolve。
  • fetchTitles现在返回所有页面的标题数组,而非单个标题。
  • 增加全局错误捕获,方便排查请求或解析过程中的问题。

内容的提问来源于stack exchange,提问作者robots.txt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 17:35:12