web-dev-qa-db-fra.com

Analyse performante des pages avec Node.js et XPath

Je suis en train de gratter Web avec Node.js. J'aimerais utiliser XPath car je peux le générer de manière semi-automatique avec plusieurs sortes d'interface graphique. Le problème est que je ne peux pas trouver un moyen de le faire efficacement.

  1. jsdom est extrêmement lent. Il analyse un fichier de 500 Ko en une minute environ, avec une charge totale du processeur et une empreinte mémoire importante.
  2. Les bibliothèques populaires pour l'analyse HTML (par exemple, cheerio) ne prennent pas en charge XPath, ni n'exposent des DOM conformes au W3C.
  3. Il va de soi que l'analyse HTML efficace est implémentée dans WebKit. Par conséquent, utiliser phantom ou casper serait une option, mais ceux-ci doivent être exécutés d'une manière spéciale, pas seulement node <script>. Je ne peux pas compter sur le risque impliqué par ce changement. Par exemple, il est beaucoup plus difficile de trouver comment exécuter node-inspector avec phantom.
  4. Spooky est une option, mais c'est assez buggé , de sorte qu'il ne s'exécute pas du tout sur ma machine.

Quelle est la bonne façon d’analyser une page HTML avec XPath?

26
polkovnikov.ph

Vous pouvez le faire en plusieurs étapes.

  1. Analyser le code HTML avec parse5. La mauvaise partie est que le résultat n'est pas DOM. Bien que ce soit assez rapide et compatible avec le W3C.
  2. Sérialisez-le au format XHTML avec xmlserializer qui accepte les structures de type parse5 de type DOM en entrée.
  3. Analyser à nouveau ce fichier XHTML avec xmldom. Maintenant, vous avez enfin ce DOM.
  4. La bibliothèque xpath repose sur xmldom, vous permettant d'exécuter des requêtes XPath. Sachez que XHTML a son propre espace de noms et que les requêtes telles que //a ne fonctionneront pas.

Enfin, vous obtenez quelque chose comme ça.

const fs = require('mz/fs');
const xpath = require('xpath');
const parse5 = require('parse5');
const xmlser = require('xmlserializer');
const dom = require('xmldom').DOMParser;

(async () => {
    const html = await fs.readFile('./test.htm');
    const document = parse5.parse(html.toString());
    const xhtml = xmlser.serializeToString(document);
    const doc = new dom().parseFromString(xhtml);
    const select = xpath.useNamespaces({"x": "http://www.w3.org/1999/xhtml"});
    const nodes = select("//x:a/@href", doc);
    console.log(nodes);
})();
32
pda

Je viens de commencer à utiliser npm install htmlstrip-native qui utilise une implémentation native pour analyser et extraire les parties html pertinentes. Il prétend être 50 fois plus rapide que l'implémentation JS pure (je n'ai pas vérifié cette affirmation).

Selon vos besoins, vous pouvez utiliser directement html-strip ou lever le code et les liaisons pour vous faire posséder le C++ utilisé en interne dans htmlstrip-native

Si vous voulez utiliser xpath, utilisez le wrapper déjà disponible ici; https://www.npmjs.org/package/xpath

1
Soren

Je pense que l'osmose est ce que vous cherchez.

  • Utilise les liaisons natives libxml C
  • Prend en charge les hybrides de sélecteur CSS 3.0 et XPath 1.0
  • Sélecteurs Sizzle, sélecteurs Slick, etc.
  • Pas de grandes dépendances comme jQuery, cheerio ou jsdom
  • Fonctionnalités de l'analyseur HTML

    • Analyse rapide
    • Recherche très rapide
    • Petite empreinte mémoire
  • Fonctionnalités HTML DOM

    • Charger et rechercher du contenu ajax
    • Interaction et événements DOM
    • Exécuter des scripts intégrés et distants
    • Exécuter du code dans le DOM

Voici un exemple:

osmosis.get(url)
    .find('//div[@class]/ul[2]/li')
    .then(function () {
        count++;
    })
    .done(function () {
        assert.ok(count == 2);
        assert.done();
    });
1
rchipka

Il n’y aura peut-être jamais une bonne façon d’analyser des pages HTML. Une toute première revue sur le web raclant et crawling me montre que Scrapy peut être un bon candidat pour votre besoin. Il accepte les sélecteurs CSS et XPath. Dans le domaine de Node.js, nous avons un joli nouveau module node-osmosis . Ce module est basé sur libxmljs, il est donc supposé prendre en charge CSS et XPath bien que je n’aie trouvé aucun exemple utilisant XPath.

0
pateheo