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.
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.cheerio
) ne prennent pas en charge XPath, ni n'exposent des DOM conformes au W3C.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
.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?
Vous pouvez le faire en plusieurs étapes.
parse5
. La mauvaise partie est que le résultat n'est pas DOM. Bien que ce soit assez rapide et compatible avec le W3C.xmlserializer
qui accepte les structures de type parse5
de type DOM en entrée.xmldom
. Maintenant, vous avez enfin ce DOM.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);
})();
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
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
osmosis.get(url)
.find('//div[@class]/ul[2]/li')
.then(function () {
count++;
})
.done(function () {
assert.ok(count == 2);
assert.done();
});
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.