Extrahieren Sie den gesamten Textinhalt in der HTML-Sammlung in ein Array mit Javascript
Hier sind die Rohdaten
anycasestr = "<div style="color: rgb(51, 51, 51); background-color: rgb(253, 246, 227); font-family: Menlo, Monaco, "Courier New", monospace; font-size: 12px; line-height: 18px;"><div>refinement</div><div>decent</div><div>elegant</div></div>";
um den gesamten Textinhalt in ein Array wie ["Verfeinerung", "anständig", "elegant"] zu extrahieren
Ich habe diesen Code geschrieben (jquery wurde aufgenommen)
htmlObject = $(anycasestr);
arr = Array.prototype.slice.call(htmlObject[0].getElementsByTagName("div"));
arr_page = [];
for (i = 0; i < 3; i++) {
arr_page.push(arr[i].textContent);
}
Es produziert was ich will.
Ich mache mir nur Sorgen, ob es auf elegante Weise umgesetzt wird. Könnte sich jemand das ansehen?
Sollte ich zum Beispiel xpath oder etwas anderes verwenden, um rechnerische Probleme zu lösen?
Antworten
Deklarieren Sie Ihre Variablen. Wenn Sie eine Variable zuweisen oder referenzieren, ohne sie vorher zu definieren, erstellen Sie entweder (1) implizit eine Eigenschaft für das globale Objekt (was zu seltsamen Fehlern führen kann) oder (2) werfen einen Fehler aus, wenn Sie dies tun laufen im strengen Modus. Sie definieren derzeit keine Ihrer Variablen. Beheben Sie das Problem const, letindem Sie sie beim ersten Zuweisen vor sie stellen (oder bei Bedarf vor sie stellen), z const htmlObject = $(anycasestr);.
jQuery- oder DOM-Methoden? Sie verwenden jQuery, um die Zeichenfolge in eine jQuery-Auflistung von Elementen umzuwandeln, aber dann verwenden Sie getElementsByTagName, um untergeordnete Elemente auszuwählen. Wenn Sie jQuery verwenden, können Sie die untergeordneten <div>Elemente präzise und konsistent auswählen . Um untergeordnete Elemente eines Elements zu finden, das einem bestimmten Tag-Namen entspricht, rufen Sie .finddie jQuery-Auflistung auf. Anschließend können Sie .mapdas gefundene Element aktivieren jQuery-Elemente in eine Sammlung nur des Textes der Elemente:
const $parent = $(anycasestr); const arr = $parent.find('div')
.map((_, child) => child.textContent)
.get(); // turn the jQuery collection of strings into an array of strings
const anycasestr = `<div style="color: rgb(51, 51, 51); background-color: rgb(253, 246, 227); font-family: Menlo, Monaco, "Courier New", monospace; font-size: 12px; line-height: 18px;"><div>refinement</div><div>decent</div><div>elegant</div></div>`;
const $parent = $(anycasestr);
const arr = $parent.find('div')
.map((_, child) => child.textContent)
.get(); // turn the jQuery collection of strings into an array of strings
console.log(arr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Oder Sie können stattdessen DOMParser verwenden. Wenn Sie DOMParser anstelle von jQuery verwenden, um den Text in eine Sammlung von Elementen umzuwandeln, können Sie die versehentliche Ausführung bösartiger Skripts vermeiden. Beispiel für einen Exploit mit jQuery:
const anycasestr = `<img src="" onerror="alert('evil')">`;
const $parent = $(anycasestr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Mit DOMParser:
const anycasestr = `<div style="color: rgb(51, 51, 51); background-color: rgb(253, 246, 227); font-family: Menlo, Monaco, "Courier New", monospace; font-size: 12px; line-height: 18px;"><div>refinement</div><div>decent</div><div>elegant</div></div>`;
const doc = new DOMParser().parseFromString(anycasestr, 'text/html');
const arr = [...doc.querySelectorAll('div > div')]
.map(div => div.textContent);
console.log(arr);
Die Abfragezeichenfolge div > divwählt <div>Elemente aus, die direkte untergeordnete Elemente eines anderen sind <div>. Es funktioniert genauso wie CSS-Selektoren. querySelectorAllist ein großartiges Werkzeug für die präzise Auswahl von Elementen - es kann auf einen Blick einfacher zu schreiben und zu verstehen sein als andere Methoden (wie Ihr Original htmlObject[0].getElementsByTagName("div")).
Array.prototype.slice.callist ein bisschen ausführlich - in nicht alten Umgebungen können Sie stattdessen die Spread-Syntax verwenden, wie ich es oben getan habe. Das gleichzeitige Erstellen eines Arrays durch Mapping ist auch etwas eleganter als das Deklarieren eines Arrays und das anschließende Erstellen eines Arrays .push.
Wenn Sie mehr <div>Kinder hätten und nur den Text aus den ersten drei von ihnen übernehmen möchten, wäre dies für .slicedas Array von Elementen funktionaler, anstatt eine Iterationszahl in eine forSchleife zu setzen:
const anycasestr = `<div style="color: rgb(51, 51, 51); background-color: rgb(253, 246, 227); font-family: Menlo, Monaco, "Courier New", monospace; font-size: 12px; line-height: 18px;">
<div>refinement</div>
<div>decent</div>
<div>elegant</div>
<div>don't include me</div>
<div>don't include me</div>
<div>don't include me</div>
</div>`;
const doc = new DOMParser().parseFromString(anycasestr, 'text/html');
const arr = [...doc.querySelectorAll('div > div')]
.slice(0, 3)
.map(div => div.textContent);
console.log(arr);
in Bezug auf rechnerische Bedenken?
Wenn das zu analysierende Material nicht unangemessen groß ist , ist die Leistung für solche Dinge kein Problem. Es ist besser, sauberen, lesbaren und wartbaren Code zu schreiben. Wenn Sie später feststellen, dass die Ausführung eines Objekts länger dauert als ideal, können Sie den Engpass identifizieren und dann herausfinden, wie Sie ihn beheben können. (Aber dies wird mit ziemlicher Sicherheit nicht der Engpass sein.)