INT values from website HTML with "pure" JavaScript > exract and put into array

83 views Asked by At

I want to modify my existing Scriptable widget for iOS, showing a so called "blood groups barometer", meaning the current status of blood reserves at the German Red Cross and Swiss Red Cross.

There is a private blood provider, called Haema - and I want to add their barometer to the script / widget.

I have found this website, where the status is given in the source code, in the form of file names of SVG images to the corresponding blood group:

<div class="blood-demand">
  <div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-50-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">A+</div></div>
  <div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-100-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">A-</div></div>
  <div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-75-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">0+</div></div>
  <div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-100-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">0-</div></div>
  <div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-50-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">B+</div></div>
  <div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-100-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">B-</div></div>
  <div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-50-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">AB+</div></div>
  <div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-75-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">AB-</div></div>
</div>

Depending on the percent value provided in the file name, I want to create an array which stores that percent value:

...
let result={};
result.a_plus     = <how to get percent value as int?>;
result.b_plus     = <how to get percent value as int?>;
result.ab_plus    = <how to get percent value as int?>;
result.zero_plus  = <how to get percent value as int?>;
result.a_neg      = <how to get percent value as int?>;
result.b_neg      = <how to get percent value as int?>;
result.ab_neg     = <how to get percent value as int?>;
result.zero_neg   = <how to get percent value as int?>;
...
if      (i <=  15){ return ""; }
else if (i <=  25){ return ""; }
else if (i <=  50){ return ""; }
else if (i <=  75){ return ""; }
else if (i <= 100){ return ""; }
...

The point is, that Scriptable is not working with jQuery. But I am able to payload the full HTML with the following:

const url = `https://www.haema.de/blutspende/`;      
let request = new Request(url)
let payload = await request.loadString()
let stack = widget.addStack()
const infoText = stack.addText(payload);

Any hint, how I can extract the percent (integer) values from the single blood groups? Thx in advance.

Update #1

It seems that 'document.querySelectorAll' can be an alternative for DOMParser(), as DOMParser() does not work:

const url = 'https://xxx/'
const wv = new WebView() // working within Scriptable
await wv.loadURL(url)

let js = `Array.from(document.querySelectorAll('div.blood-demand div')).map( div => Array.from(div.children).map(div => div.innerText, img => img.src))`;
const data = await wv.evaluateJavaScript(js)

Unfortunately, the result currently looks like this:

[["","A+"],[],["","A-"],[],["","0+"],[],["","0-"],[],["","B+"],[],["","B-"],[],["","AB+"],[],["","AB-"],[]]

Any hint, how to modify the query to receive something like that (taking the extracted example HTML from above?

[[50,"A+"],[100,"A-"],[75,"0+"],[100,"0-"],[50,"B+"],[100,"B-"],[50,"AB+"],[75,"AB-"]]

1

There are 1 answers

3
Roko C. Buljan On

Given you're able to get the HTML you snippeted above:

  • Create a function getSymbol(n) that returns the icons (stats) string given a Number n
  • Create a function parser() that returns an Object with the necessary data.
  • To get a number (percent) from a string use .replace(/\D/g, "") where \D stands for "Not a digit" - which basically removes anything that is not one. Remember that if your src value changes in the future you'll have to modify the JS accordingly.

const getSymbol = (n) => {
  return n <= 15 ? "" :
    n <= 25 ? "" :
    n <= 50 ? "" :
    n <= 75 ? "" :
    "";
};

const parser = (HTMLString) => {

  const DOC = new DOMParser().parseFromString(HTMLString, "text/html");
  const elsItems = DOC.querySelectorAll(".blood-demand--item");
  
  const result = {};
  
  elsItems.forEach(elItem => {
    const txt = elItem.textContent.replace(/[\-+]/, (v) => ({"+": "_plus", "-": "_neg"}[v]));
    const pct = Number(elItem.querySelector("img").src.replace(/\D/g, ""));
    result[txt] = getSymbol(pct);
  });
  
  return result;
};

// Use like:
const HTMLResponse = `<div class="blood-demand"><div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-50-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">A+</div></div><div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-100-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">A-</div></div><div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-15-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">0+</div></div><div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-100-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">0-</div></div><div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-50-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">B+</div></div><div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-25-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">B-</div></div><div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-50-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">AB+</div></div><div class="blood-demand--item"><img src="/fileadmin/user_upload/Blutspende/Blutampel/Transfusius-75-prozent-haema.svg" width="162" height="300"><div class="blood-demand--title">AB-</div></div></div>`;
const result = parser(HTMLResponse);
console.log(result);