JavaScript Parsen einer Webseite/Arbeiten mit DOM in NodeJS?

Status
Für weitere Antworten geschlossen.

shoa66

Lt. Junior Grade
Registriert
Mai 2005
Beiträge
317
Hey Leute,

ich möchte eine Webseite scrapen und parsen und mit den Informationen von dort weiterarbeiten, genauer gesagt diese Seite.

Interessant sind dabei für mich die Waffennamen (<div class="panel-heading item-title">) sowie die Preise (<span class="item-price-display">). Via Browser (Tampermonkey/Greasemonkey/Controlfreak usw.) wäre das ja relativ einfach, da man einfach auf die DOM Elemente und Funktionen zugreifen kann, aber via NodeJS in der Konsole geht das ja leider nicht so einfach.

Ich hab mir dazu schon einige Libraries angesehen und bin auf folgende Optionen gestoßen:

Einzuschätzen was davon die beste Wahl für mich ist (weil am einfachsten zu handhaben und idealerweise auch am schnellsten) überfordert mich leider etwas, da ich nicht viel Erfahrung in der Entwicklung besitze und mich aktuell noch Step für Step rantaste.

Versucht habe ich es bisher mit cheerio und dom-parser, leider ohne Erfolg:

Code:
var request = require('request');
var DomParser = require('dom-parser');
var parser = new DomParser();

function search() {
    var bench = new Date().getTime();
    request({
        url: "https://bitskins.com/?appid=730&is_stattrak=0&has_stickers=0&is_souvenir=0&show_trade_delayed_items=1&sort_by=created_at&order=asc",
        method: "GET",
        json: false,
    }, function (error, response, data) {
        if (typeof data === "undefined") {
            console.log("Error, no HTML page received");
        }
        else {
            console.log("Received HTML page. Processed data in " + ((new Date().getTime() - bench) / 1000 + " seconds."));
            var html = parser.parseFromString(data);
            const name = html.getElementsByClassName("panel-heading item-title");
            console.log(name);
        }
    });
}

search();

Das Ergebnis sieht dann so aus (es sind zwar 60 Gegenstände, wie es auch sein soll, nur sieht es sehr strange aus):
Unbenannt.png

Eigentlich müsste es ja auch heißen
Code:
"html.document.getElementsByClassName("panel-heading item-title")
und davon dann an Stelle [0] usw. die .innerHTML, aber document ist nicht definiert bzw. kein Objekt.

Hat jemand eine Idee was ich da falsch mache?

Code:
const request = require('request');
const cheerio = require('cheerio')

function search() {
    var bench = new Date().getTime();
    request({
        url: "https://bitskins.com/?appid=730&is_stattrak=0&has_stickers=0&is_souvenir=0&show_trade_delayed_items=1&sort_by=created_at&order=asc",
        method: "GET",
        json: false,
    }, function (error, response, html) {
        if (error || typeof html === "undefined") {
            console.log("Error, no HTML page received");
        }
        else {
            console.log("Received HTML page. Processed data in " + ((new Date().getTime() - bench) / 1000 + " seconds."));
            const $ = cheerio.load(html);
            var name = $('.panel-heading item-title');
            var output = name.text();
            console.log(output);
        }
    });
}

search();

Mein Versuch mit Cheerio lief auch nicht viel besser... der output ist einfach leer.

Etwas ausführlichere Tutorials finde ich leider nur für Cheerio, da wird aber nicht das gemacht was ich brauche bzw. nur mit deutlich einfacheren Blog-Seiten gearbeitet.

Wäre über Hilfe jeglicher Art bzw. Links zu Tutorials usw. sehr dankbar. Sitze da jetzt seit Stunden dran und drehe mich im Kreis :(
 
Zuletzt bearbeitet:
As a condition to your use of the Service, you agree not to:
...
(g) systematically retrieve data or other content from the Service to create or compile, directly or indirectly, in single or multiple downloads, a collection, compilation, database, directory or the like, whether by manual methods, through the use of bots, crawlers, or spiders, or otherwise;
https://bitskins.com/tos

Was Du vor hast verstößt gegen die Nutzungsbedingungen der Seite.

Die bieten selber eine API an. Schon versucht, ob Du mit deren Hilfe an Deine gewünschten Daten kommst?
 
Andreas_ schrieb:
Die bieten selber eine API an. Schon versucht, ob Du mit deren Hilfe an Deine gewünschten Daten kommst?

Ja, die API ist laut praktischer Erfahrung und auch deren Support "nicht lossless", sprich mehr oder weniger nutzlos. Daher ja dieser Umweg.

Zu den TOS: In in der Praxis sind zumindest Userscripts für Tampermonkey usw. seit Jahren kein Problem. Nur in NodeJS direkt wäre es deutlich praktischer und performanter, daher wäre es schön wenn wir meine Probleme mal rein theoretisch weiterdiskutieren könnten :D

Außerdem ist die Auslegung strittig. Die Daten werden nicht für eine compilation/database genutzt, sondern um die Gegenstände zu kaufen und somit die Seite tatsächlich auch zu nutzen.
 
Zuletzt bearbeitet:
Die Auslegung ist kaum strittig ...
systematically retrieve data ... to create ... a collection
Das ist genau das, was Du vor hast.

Die haben nicht umsonst bei der API eine Beschränkung auf stündliche Aktualisierung.
 
  • Gefällt mir
Reaktionen: Darrel und abcddcba
1. ist nicht legal
2. Was ist ueberhaupt das Problem mit dem Code oben? Der macht doch was er soll, gibt dir die Knoten im Baum zurueck. Woran scheitert es jetzt da noch?
Was genau geht nicht, alle APIs bieten doch mehr oder weniger die gleichen Methoden. Und du waehlst ja eh per CSS Selector aus, deswegen seh ich das Problem nicht. dom-parser ist uebrigens genau die API, die nur wenig von allem kann. cheerio is analog zu JQuery, also genauso leicht zu bedienen. htmlparser2 und jsdom sind gaengige APIs, die alles koennen
3. Wozu macht man sowas ueberhaupt, ich persoenlich wuede mein Geld nicht fuer so einen Schrott wie Waffenskins etc. ausgeben
4. ist nicht legal
 
Ich frage mich immer was Leute dazu veranlasst, solche nicht hilfreichen Kommentare zu verfassen und einen auf Internet Polizei zu machen?

1. Nein, ich möchte keine Collection erzeugen sondern die Daten nur on the Fly zum Kaufen von Gegenständen (normale Funktionen der Webseite) nutzen
2. Ich kenne genug Leute, die seit zig Monaten bis Jahren solche Userscripts nutzen ohne gesperrt zu werden. Ergo scheint es die Betreiber der Seite auch in der Praxis nicht zu stören. Frage mich also wieso du dich jetzt so an deren TOS ereiferst statt konstruktiv zu helfen. De facto hättest du dir alle Posts bisher sparen können, da sie nicht hilfreich sind. Im Gegenteil!
3. Beschränkung auf stündliche Aktualisierung? Can't tell if trolling or just st.... Die API besteht aus websockets, mit denen man live Daten gestreamt bekommt (nur leider unvollständig), siehe https://bitskins.com/websockets. Außerdem gibt es normale API requests, von denen man 8 pro Sekunde schicken darf:
https://bitskins.com/api schrieb:
Default API throttle limits are 8 requests per second. Contact us if you need higher limits.
4. Selbst wenn es tatsächlich gegen die TOS wäre, wäre das ganz allein meine Sorge und tut hier thematisch gar nichts zur Sache.

/edit:

abcddcba schrieb:
2. Was ist ueberhaupt das Problem mit dem Code oben? Der macht doch was er soll, gibt dir die Knoten im Baum zurueck. Woran scheitert es jetzt da noch?

Ich möchte, in NodeJS, eine Ausgabe wie von diesem Userscript:
Code:
    var name = document.getElementsByClassName("panel-heading item-title");
    var itemName = name[0].innerHTML;
    var price = document.getElementsByClassName("item-price-display");
    var itemPrice = price[0].innerHTML;
    console.log(itemName + "for " + itemPrice);

Die Ausgabe dieses Userscripts lautet dann: "Chroma 2 Case Key for $2.18". Das kriege ich in NodeJS bisher einfach nicht hin.

Anders formuliert: Ich suche eine Library/einen Weg, der mir den String der vom HTTP Request (GET) kommt, so formatiert dass ich bequem (via DOM oder via JSON) ohne viel RegEx zu benutzen, an die oben genannten Daten komme.

abcddcba schrieb:
3. Wozu macht man sowas ueberhaupt, ich persoenlich wuede mein Geld nicht fuer so einen Schrott wie Waffenskins etc. ausgeben

Wozu ist das relevant? Ich habe ein Coding Problem und brauche Hilfe, weitere Diskussionen sind nicht hilfreich und unnötig. Kann ja jeder mit seinem Geld machen was er will, oder nicht?

Wenn jemand nach einer Kaufberatung für eine Grafikkarte zum Spielen bittet, postest du ja auch nicht "Wieso willst du überhaupt PC-Spiele spielen, mach doch lieber etwas Sport an der frischen Luft"?!

abcddcba schrieb:
1. ist nicht legal
4. ist nicht legal

Suchmaschinen und Crawler Betreiber wie Google sind also auch illegal? XD

Weiterhin: TOS sind nicht gleich geltendem Recht. Zeit mir mal bitte einen Paragraph im deutsche Strafrecht, der das Parsen von Webseiten verbietet 😉
 
Zuletzt bearbeitet:
abcddcba schrieb:
1. ist nicht legal
4. ist nicht legal

Illegal (verstößt gegen Gesetzte)? Nein.
Verboten (durch Nutzungsbedingungen)? Ja.

Das sind zwei sehr verschiedene Dinge. Die werden deswegen niemandem die Polizei nach Hause schicken. Dazu fehlt jede Grundlage. Wenn es dem Betreiber nicht passt, darf er den Account sperren und das wars. Wenn er wirklich sauer ist, schickt er eine "Abmahnung" bzw. fordert eine Unterlassungserklärung.

Der "Hackerparagraf" greift nur bei einer "nichtöffentlichen Datenübermittlung" oder "Überwindung der Zugangssicherung". Keins davon ist hier gegeben. Die Informationen stehen frei zugänglich im Netz.
Solange das Skript nicht irgendwie die Seite lahm legt, sehe ich da absolut kein rechtliches Problem.
Ergänzung ()

@shoa66 Du warst schon so schon fast dran mit der dom-parser Lösung. Hier meine Variante.


Code:
var request = require('request');
var DomParser = require('dom-parser');
var parser = new DomParser();
function search() {
    var bench = new Date().getTime();
    request({
        url: "https://bitskins.com/?appid=730&is_stattrak=0&has_stickers=0&is_souvenir=0&show_trade_delayed_items=1&sort_by=created_at&order=asc",
        method: "GET",
        json: false,
    }, function (error, response, data) {
        if (typeof data === "undefined") {
            console.log("Error, no HTML page received");
        }
        else {
            console.log("Received HTML page. Processed data in " + ((new Date().getTime() - bench) / 1000 + " seconds."));
            const html = parser.parseFromString(data);
            const names = html.getElementsByClassName("panel-heading item-title")
                .map(node => node.innerHTML.trim())
                .filter(name => name != '');
            console.log(names);
        }
    });
}
search();


Code:
map(node => node.innerHTML.trim())
Nimmt von jedem gefundenen DOM-Node das innerHTML und
Code:
trim()
schneidet vorne und hinten Whitepsace ab.


Code:
.filter(name => name != '')
Schmeißt dann alle leeren Strings aus der Liste.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: shoa66
shoa66 schrieb:
Ich frage mich immer was Leute dazu veranlasst, solche nicht hilfreichen Kommentare zu verfassen und einen auf Internet Polizei zu machen?
Und ich frage mich immer, was Leute veranlasst, erst nach Hilfe zu fragen und dann sich so "besch...eiden" zu verhalten.
Ich für meinen Teil helfe z.B. hier niemanden, der sich so verhält wie Du. Und so dürften hier im Forum einige denken (imho zu Recht). Und mehr als Dich darauf aufmerksam gemacht, haben die user nicht.
 
  • Gefällt mir
Reaktionen: BeBur
Simon#G schrieb:
Illegal (verstößt gegen Gesetzte)? Nein.
Da in Deutschland zu mindestens auch das Urheberrecht eine Rolle spielt und seit einiger Zeit auch Datenbanken entsprechenden Schutz genießen, liegst Du in diesem Punkt falsch.
§ 87b UrhG

Der Eigentümer der Daten entscheidet, welche Form der Nutzung er erlaubt. Dies hat er eindeutig durch seine TOS getan. Damit ist das Vorhaben des TE ein klarer Verstoß gegen des Urheberrecht. Die Forenregeln sind in diesem Fall auch eindeutig - nämlich das derartiges nicht geduldet wird.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Demon_666 und Simon#G
Andreas_ schrieb:
Da in Deutschland zu mindestens auch das Urheberrecht eine Rolle spielt und seit einiger Zeit auch Datenbanken entsprechenden Schutz genießen, liegst Du in diesem Punkt falsch.
§ 87b UrhG
er veröffentlicht die Daten nicht, ER teilt die Daten nicht weiter?
Ergänzung ()

Demon_666 schrieb:
Und ich frage mich immer, was Leute veranlasst, erst nach Hilfe zu fragen und dann sich so "besch...eiden" zu verhalten.
Also ich finde es verständlich.
Mich würde es auch nerven, wenn ich eine Frage stelle und mit lauter OT vollgespamt werden würde.
 
  • Gefällt mir
Reaktionen: xenon-seven und shoa66
new Account() schrieb:
Also ich finde es verständlich.
Mich würde es auch nerven, wenn ich eine Frage stelle und mit lauter OT vollgespamt werden würde.
Hmm, darauf aufmerksam machen, dass man etwas nicht Legales macht, rechtfertigt also das Anmachen der Leute, die man um Hilfe fragt? Komische Denke...
Und ob etwas rechtens ist, hat imho immer was mit einem topic zu tun....
justmy2cents
Aber langsam wird es wirklich OT....
 
Zuletzt bearbeitet:
Simon#G schrieb:
Code:
map(node => node.innerHTML.trim())
Nimmt von jedem gefundenen DOM-Node das innerHTML und
Code:
trim()
schneidet vorne und hinten Whitepsace ab.


Code:
.filter(name => name != '')
Schmeißt dann alle leeren Strings aus der Liste.

Sehr geil, hab 1000 Dank! :love: Darf ich fragen, wie du zu dieser Lösung gekommen bist, damit ich für die Zukunft lerne mir ggf. selber zu helfen? Hast du das schon gekannt oder via Dokumentation der Lib irgendwo recherchiert?

Demon_666 schrieb:
Und ich frage mich immer, was Leute veranlasst, erst nach Hilfe zu fragen und dann sich so "besch...eiden" zu verhalten.
Ich für meinen Teil helfe z.B. hier niemanden, der sich so verhält wie Du. Und so dürften hier im Forum einige denken (imho zu Recht). Und mehr als Dich darauf aufmerksam gemacht, haben die user nicht.

Da divergieren unsere Ansichten wohl. Ich verhalte mich meiner Meinung nach nicht bescheiden sondern reagiere angemessen bzw. noch nett (hatte eigentlich erst was anderes geschrieben) auf Personen, die zum einen nur OT posten und zum anderen mich noch hinstellen als würde ich was illegales machen - und dabei sogar noch falsch liegen.

Demon_666 schrieb:
Und ob etwas rechtens ist, hat imho immer was mit einem topic zu tun....

Auch hier verstehe ich die Logik nicht ganz und stimme dir nicht zu. Selbst wenn es wirklich illegal gewesen wäre, ginge es hier um ein theoretisches Coding Problem, nicht um dich rechtlichen Implikationen (die ich dann vor einem praktischen Einsatz ggf. mit einen Anwalt und nicht in einem IT-Forum diskutieren würde). Außerdem wäre nicht die Entwicklung bereits illegal, sondern erst der Einsatz.

Andreas_ schrieb:
Da in Deutschland zu mindestens auch das Urheberrecht eine Rolle spielt und seit einiger Zeit auch Datenbanken entsprechenden Schutz genießen, liegst Du in diesem Punkt falsch.
§ 87b UrhG

Nein, du liegst erneut falsch, denn die Daten werden weder veröffentlicht noch geteilt. new Account () hat also absolut recht.
 
Zuletzt bearbeitet:
shoa66 schrieb:
Sehr geil, hab 1000 Dank! :love: Darf ich fragen, wie du zu dieser Lösung gekommen bist, damit ich für die Zukunft lerne mir ggf. selber zu helfen? Hast du das schon gekannt oder via Dokumentation der Lib irgendwo recherchiert?

Kein Ding :) map und filter kannte ich konzeptionell schon und wusste auch, dass man die in Node verwenden kann. Die braucht man ständig, wenn man mit Listen arbeitet. Bzw. hat man es damit einfacher. Nur die genaue Verwendung musste ich nachschlagen.
Dass du an die innerHTML-Eigenschaft ran willst, stand ja schon in deinem Post. trim hab ich erraten. Gibts in anderen Sprachen ja auch.
 
  • Gefällt mir
Reaktionen: shoa66
Status
Für weitere Antworten geschlossen.
Zurück
Oben