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

优化Cheerio抓取循环 单次遍历获取90分钟内最后比赛比分

问题场景

在Google Apps Script环境下使用Cheerio开展网页数据抓取工作,目标页面为足球赛事进球记录页,进球数据存储在class属性为scorer-info的ul列表中:

  • 每个li子节点对应一次进球事件
  • 节点内包含class为score的span元素存储当前比分
  • li下class为scorer的span内包含class为minute的span元素存储进球分钟数
  • 分钟与比分按进球顺序一一对应
需求说明

匹配进球分钟数小于等于90时对应的最后一个比分值,以提供的示例数据为例,符合要求的结果为67分钟对应的比分2-2。

原有实现问题

原有代码逻辑为分别通过选择器独立获取所有span.minute、span.score元素,经过两次each遍历将提取处理后的分钟值、比分值存入两个独立二维数组,再通过第三次for循环遍历数组逐次更新符合分钟≤90条件的比分值,存在明显缺陷:

  • 需要维护多个额外存储数组,内存占用高
  • 三轮遍历+两次独立DOM查询带来不必要的执行开销
  • 靠索引对齐两个独立元素集合的逻辑鲁棒性差
  • 冗余代码多,可维护性低

原有可正常运行的代码如下:

function score() {
  var ss = SpreadsheetApp.getActive().getSheetByName('copy');
  var response = UrlFetchApp.fetch('URL URL URL URL', {muteHttpExceptions: true});
  if (response.getResponseCode() == 404) {
  } else {
    var contentText = response.getContentText();
    var $ = Cheerio.load(contentText);
    
    var list_minutes = [];
    var list_score = [];

    var minute_goal = $('ul.scorer-info > li > span.scorer > span.minute');
    var score_goal = $('ul.scorer-info > li > span.score');

    minute_goal.each((index, element) => {list_minutes.push([($(element).text().trim()).substring(0, ($(element).text().trim()).indexOf("'"))]);});
    score_goal.each((index, element) => {list_score.push([($(element).text().trim()).replace(/ /g,'')]);});

    var before_90 = '0-0';

    var i=0;
    var max = list_minutes.length
    for(i; i<max; i++){
      if (list_minutes[i][0] <= 90) {
        before_90 = list_score[i][0];
      }
    }
    Logger.log(before_90)
  }
}

原有代码运行后可正确输出结果2-2。

优化实现方案

直接以单条进球事件对应的li节点为最小遍历单位,单次DOM遍历即可完成所有判断和结果更新,完全去掉中间存储数组,DOM查询和遍历总次数从3次降至1次。
优化后代码如下:

function score() {
  var ss = SpreadsheetApp.getActive().getSheetByName('copy');
  var response = UrlFetchApp.fetch('URL URL URL URL', {muteHttpExceptions: true});
  if (response.getResponseCode() === 404) return;
  
  const $ = Cheerio.load(response.getContentText());
  // 初始化默认比分
  let before_90 = '0-0';

  // 单次遍历所有进球条目,直接在条目上下文内提取所需数据
  $('ul.scorer-info > li').each((_, entry) => {
    const $entry = $(entry);
    // 提取当前进球的分钟数
    const minuteRaw = $entry.find('span.minute').text().trim();
    const minute = Number(minuteRaw.substring(0, minuteRaw.indexOf("'")));
    // 符合时间条件就更新比分,按进球顺序遍历后最终留存的就是最晚的合规比分
    if (minute <= 90) {
      before_90 = $entry.find('span.score').text().trim().replace(/\s/g, '');
    }
  });

  Logger.log(before_90);
  return before_90;
}

优化说明:

  • 以li为遍历单位,在单个节点上下文内同时查询分钟和比分,避免了分开查询元素集合再靠索引对齐的不可靠逻辑
  • 完全移除两个中间存储数组,减少不必要的内存占用
  • 仅执行1次DOM遍历,脚本执行速度提升明显
  • 简化了404分支的空代码块,逻辑更简洁
  • 文本处理规则和原有逻辑完全一致,输出结果和原代码100%兼容,示例场景下仍返回2-2

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 13:54:04