'ignore if constant not found (where constant is regex)

I hit a snag. This code snippet works great to get film ratings, when they exist. It errors out when it gets to a record that doesn't include the regex. "TypeError: Cannot read property '0' of null"

  const ratingPass1 = /<span class="rating rated-([\s\S]*?)">/g;
  const ratingPass2 = /(?<=<span class="rating rated-).*?(?=\">)/g;

for(var i = 0; i < 18; i++)
  {  var rating1String = results[i].match(ratingPass1);
    Logger.log('content: ' + rating1String[0]);
    var rating2String = rating1String[0].match(ratingPass2);
--> error is here  Logger.log('content: ' + rating2String[0]); 

I'm too new to javascript to know how to implement an 'includes' or 'contains' or something of that ilk in this code. But I'm getting not too bad with Regex, and figured I might be able to turn the regex into one large excluded group with the included group within it, so I tried:

const ratingPass1 = /(?:<span class="rating rated-([\s\S]*?)">)/g;
var rating1String = results[i].match(ratingPass1);
    Logger.log('content: ' + rating1String[0]);

but I keep getting the error, and I should, I guess because I'm still saying "find it, but it exclude it", where I need a "if you don't find it, just ignore it". Maybe it's the "match" in

var rating1String = results[i].match(ratingPass1);
    Logger.log('content: ' + rating1String[0]);

that could be changed to say something like match OR ignore if null?


Update: It took quite a few hours, but I figured something out. Might just work by some fluke, but at least it works!

I replaced the variables and logging info with the following:

 var rating0String = ""; 
 var rating1String = results[i].match(ratingPass1);
  if(!ratingPass1){
    Logger.log('content: ' + rating0String);
    }else{
    Logger.log('content: ' + rating1String); 
    };
  var rating2String = results[i].match(ratingPass2);
    if(!ratingPass2){
      Logger.log('content: ' + rating0String);
      }else{
        Logger.log('content: ' + rating2String);
      };


Solution 1:[1]

It can be done effectively using Cheerio library, check self-explanatory comments in code:

function matchRating()
{
  // TODO replace html with your data
  const html = '<div><span class="rating rated-one"></span><span class="rating rated-two"></span><span class="rating rated-three"></span></div>';
  
  // create Cheerio object
  const $ = Cheerio.load(html);

  const ratingPrefixForClass = 'rated-';
  // select all spans with `rating` class
  $(".rating").each((i, el) => {
    let classAttr = $(el).attr('class');
    
    // split class attribute to get list of class names, find one with needed prefix
    let ratingClassSearch = classAttr.split(' ').find(cls => cls.indexOf(ratingPrefixForClass) === 0);

    // if needed class with prefix found, log its name, and its name without prefix
    if (ratingClassSearch)
    {
      console.log(ratingClassSearch, ratingClassSearch.substring(ratingPrefixForClass.length));
    }
  });
}

Main points:

  1. Do not use regex for parsing HTML.
  2. Uses Cheerio JS library ported for Google Apps Script. To install it, you need add it as a dependency.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Kos