有没有办法改进通过 indexOf 将子字符串与搜索位置文本分开的方法?

Is there a way to improved method for separating a substring from search position text via indexOf?

我使用的方法我需要在搜索文本各部分位置时将+13-1放入计算中(const Beforeconst After) ,有没有更可靠更正确的方法?

  const PositionBefore = TextScript.indexOf(Before)+13;
  const PositionAfter = TextScript.indexOf(After)-1;

我担心的是,由于某种原因,搜索文本发生了变化,我忘记更改计算的数字,这会导致检索到的文本出错。

我 return 的文本部分是日期和时间:

2021-08-31 19:12:08
function Clock() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('Clock');
  var url = 'https://int.soccerway.com/';
  
  const contentText = UrlFetchApp.fetch(url).getContentText();
  const $ = Cheerio.load(contentText);
  
  const Before = '"timestamp":"';
  const After = '});\n    block.registerForCallbacks();';
  
  var ElementSelect = $('script:contains(' + Before + ')');
  var TextScript = ElementSelect.html().replace("\n","");
  
  const PositionBefore = TextScript.indexOf(Before)+13;
  const PositionAfter = TextScript.indexOf(After)-1;
  
  sheet.getRange(1, 1).setValue(TextScript.substring(PositionBefore, PositionAfter));
}

var TextScript中收集的示例全文:

  (function() {
    var block = new HomeMatchesBlock('block_home_matches_31', 'block_home_matches', {"block_service_id":"home_index_block_homematches","date":"2021-08-31","display":"all","timestamp":"2021-08-31 19:12:08"});
    block.registerForCallbacks();
    
    $('block_home_matches_31_1_1').observe('click', function() { block.filterContent({"display":"all"}); }.bind(block));
$('block_home_matches_31_1_2').observe('click', function() { block.filterContent({"display":"now_playing"}); }.bind(block));


      block.setAttribute('colspan_left', 2);
  block.setAttribute('colspan_right', 2);



    TimestampFormatter.format('block_home_matches_31');
  })();
  

无法消除对源内容进行结构更改的风险。

您可以采取一些措施来尽量减少忘记更改代码的可能性 - 例如,不需要硬编码 +13-1。但除此之外,还有其他原因会导致您的代码失败。

当您的代码确实失败时,让它变得非常明显可能更重要。

考虑以下示例(为简单起见,它不使用 Cheerio):

function demoHandler() {
  var url = 'https://int.soccerway.com/';
  const contentText = UrlFetchApp.fetch(url).getContentText();

  var matchedJsonString = contentText.match(/{.*?"timestamp".*?}/)[0];
  if ( matchedJsonString ) {
    try {
      var json = JSON.parse(matchedJsonString);
    } catch(err) {
      console.log( err ); // "SyntaxError..."
    }
    console.log(json.timestamp)
  } else {
    consle.log( 'Something went terribly wrong...' )
  }

}

当你运行上面的函数时,它会在控制台打印以下内容:

2021-08-31 23:18:46

它通过假设 "timestamp" 的键值是 JSON 字符串的一部分来做到这一点,从 { 开始并以 } 结束。

因此您可以提取此 JSON 字符串并将其转换为 JavaScript 对象,然后直接访问时间戳值,无需处理子字符串。

如果 JSON 无效,您将收到类似于此的显式错误:

[SyntaxError: Unexpected token c in JSON at position 0]

抓取网页数据几乎总是存在这些类型的风险:如果源结构在没有警告的情况下发生变化,您的代码可能会很脆弱并且很容易损坏。只需尝试使此类更改尽可能明显即可。在您的情况下,将错误写入电子表格并使其非常明显(红色、粗体等)。

并充分利用 try...catch 语句。参见:try...catch