Puis-je utiliser jQuery avec Node.js?

574

Est-il possible d'utiliser des sélecteurs jQuery / manipulation DOM côté serveur en utilisant Node.js?

John
la source
3
Je me demande: pourquoi utiliser côté serveur alors que vous pouvez le faire côté client?
Inanc Gumus
31
Peut-être voudrez-vous créer un scrapper Web qui récupère des informations spécifiques à intervalles réguliers et stocke les résultats dans une base de données? Ce ne serait pas aussi pratique du côté client.
Trevor
2
Vous devriez également jeter un oeil à phantomjs, qui vous permet d'émuler un côté serveur de navigateur avec le moteur V8.
Dimitri Kopriwa
2
La manipulation de @deeperx DOM côté serveur pourrait être utile lors de la création d'un robot. Voir cette réponse .
Lucio Paiva
OUI - jetez un œil à cette réponse - je préfère cela à l'utilisation de cheerio, car vous obtenez toute la puissance du sélecteur jQuery.
monika mevenkamp

Réponses:

563

Mise à jour (27-juin-18) : Il semble qu'il y ait eu une mise à jour majeure jsdomqui empêche la réponse d'origine de fonctionner. J'ai trouvé cette réponse qui explique comment l'utiliser jsdommaintenant. J'ai copié le code correspondant ci-dessous.

var jsdom = require("jsdom");
const { JSDOM } = jsdom;
const { window } = new JSDOM();
const { document } = (new JSDOM('')).window;
global.document = document;

var $ = jQuery = require('jquery')(window);

Remarque: La réponse d'origine ne mentionne pas que vous devrez également installer jsdom en utilisantnpm install jsdom

Mise à jour (fin 2013) : L'équipe officielle de jQuery a finalement repris la gestion du jquerypackage sur npm:

npm install jquery

Alors:

require("jsdom").env("", function (err, window) {
    if (err) {
        console.error(err);
        return;
    }
    var $ = require("jquery")(window);
});

Philippe Rathé
la source
43
Est-il possible d'utiliser jQuery ajax à partir de node.js avec ce module npm?
ajsie
22
Ne s'installe pas sur Windows (sans travaux importants ), auquel cas je recommanderais le module Cheerio: matthewmueller.github.com/cheerio
Simon East
7
+1 pour montrer où trouver npm :) la plupart des gens ont la mauvaise habitude de simplement mentionner des choses comme si cela devait être donné (bon sens)
Val
12
Cela revient require("...").env is not a function.
Banderi
4
@Banderi même avec moi, une idée? l'erreur:TypeError: require(...).env is not a function
coderInrRain
58

Oui, vous pouvez, en utilisant une bibliothèque que j'ai créée appelée nodeQuery

var Express = require('express')
    , dnode = require('dnode')
    , nQuery = require('nodeQuery')
    , express = Express.createServer();

var app = function ($) {
    $.on('ready', function () {
        // do some stuff to the dom in real-time
        $('body').append('Hello World');
        $('body').append('<input type="text" />');
        $('input').live('click', function () {
            console.log('input clicked');
            // ...
        });
    });
};

nQuery
    .use(app);

express
    .use(nQuery.middleware)
    .use(Express.static(__dirname + '/public'))
    .listen(3000);

dnode(nQuery.middleware).listen(express);
Thomas Blobaum
la source
20
Notez que nodeQuery change en fait la page de l'utilisateur en temps réel, donc c'est encore plus cool que ce à quoi on pourrait s'attendre.
alessioalex
Je cherchais quelque chose comme ça quand je suis tombé ici ... Je viens de regarder les packages de nœuds nQuery et jquery et nQuery a été mis à jour il y a un an où jquery était hier ... NQuery n'est-il plus développé? et jquery affecte-t-il le côté client comme le fait nQuery? Est-ce que quelqu'un les a peut-être essayés tous les deux?
Logan
2
@Logan nQuery est essentiellement juste jquery. la différence est que le code est exécuté sur le serveur et, plutôt que de fournir le code jquery au navigateur, il exécute le code sur le serveur et exécute à distance la manipulation dom vers les navigateurs connectés. Notez également que nQuery était un projet expérimental, et même si j'accepte les demandes de tirage pour corriger les bogues, il n'a jamais été créé dans un but ou un projet spécifique, donc il n'a pas eu beaucoup de commits
Thomas Blobaum
@ThomasBlobaum ne fonctionne pas pour moi, erreur: , express = Express.createServer();et TypeError: Express.createServer is not a functionune idée?
coderInrRain
@ThomasBlobaum semble que vous n'ayez pas la dernière version d'Express. Essayez npm install --save expressdans votre invite de commande.
gilbert-v
55

Au moment de la rédaction, il y a aussi le Cheerio maintenu .

Implémentation rapide, flexible et allégée du noyau jQuery conçu spécifiquement pour le serveur.

Alfred
la source
2
+1 pour Cheerio. jsdom, en revanche, est vraiment pénible à exécuter sous Windows.
Simon East
1
Cheerio peut-il utiliser des événements différés et des appels ajax?
Hoffmann
6
ne supporte pas beaucoup de sélecteurs comme:gt(1)
chovy
1
D'après mon expérience, celui-ci fonctionne le mieux. C'est beaucoup plus rapide que JSDOM.
Jason Prawn
1
@Hoffmann, j'ai passé une seconde à vérifier les documents pour vous. Non. Cheerio a uniquement des méthodes liées à DOM.
Denis
39

Vous pouvez désormais utiliser jsdom . Regardez simplement leur exemple jquery dans le répertoire examples.

Benjamin Coe
la source
un inconvénient de jQueryify () de jsdom est qu'il exécute tous les scripts de la page.
drewish
et cela ne fonctionne pas sur Windows sans beaucoup de maux de tête
Jason Goemaat
1
en 2016, vous n'avez plus besoin de jsdom - voir ma réponse: stackoverflow.com/a/40656811/3391783
low_rents
34

Un robot simple utilisant Cheerio

Voici ma formule pour créer un robot simple dans Node.js. C'est la principale raison de vouloir faire une manipulation DOM du côté serveur et c'est probablement la raison pour laquelle vous êtes arrivé ici.

Tout d'abord, utilisez requestpour télécharger la page à analyser. Une fois le téléchargement terminé, gérez-le cheerioet commencez la manipulation du DOM comme si vous utilisiez jQuery.

Exemple de travail:

var
    request = require('request'),
    cheerio = require('cheerio');

function parse(url) {
    request(url, function (error, response, body) {
        var
            $ = cheerio.load(body);

        $('.question-summary .question-hyperlink').each(function () {
            console.info($(this).text());
        });
    })
}

parse('http://stackoverflow.com/');

Cet exemple imprimera à la console toutes les principales questions affichées sur la page d'accueil SO. C'est pourquoi j'aime Node.js et sa communauté. Rien de plus simple :-)

Installer les dépendances:

demande d'installation npm cheerio

Et exécutez (en supposant que le script ci-dessus est dans le fichier crawler.js):

node crawler.js


Codage

Certaines pages auront un contenu non anglais dans un certain encodage et vous devrez le décoder UTF-8. Par exemple, une page en portugais brésilien (ou toute autre langue d'origine latine) sera probablement codée ISO-8859-1(aka "latin1"). Lorsque le décodage est nécessaire, je dis de requestne pas interpréter le contenu de quelque manière que ce soit et de l'utiliser iconv-liteà la place pour faire le travail.

Exemple de travail:

var
    request = require('request'),
    iconv = require('iconv-lite'),
    cheerio = require('cheerio');

var
    PAGE_ENCODING = 'utf-8'; // change to match page encoding

function parse(url) {
    request({
        url: url,
        encoding: null  // do not interpret content yet
    }, function (error, response, body) {
        var
            $ = cheerio.load(iconv.decode(body, PAGE_ENCODING));

        $('.question-summary .question-hyperlink').each(function () {
            console.info($(this).text());
        });
    })
}

parse('http://stackoverflow.com/');

Avant d'exécuter, installez les dépendances:

demande d'installation npm iconv-lite cheerio

Et puis finalement:

node crawler.js


Liens suivants

La prochaine étape serait de suivre les liens. Supposons que vous souhaitiez répertorier toutes les affiches de chaque question principale sur SO. Vous devez d'abord répertorier toutes les principales questions (exemple ci-dessus), puis entrer chaque lien, en analysant la page de chaque question pour obtenir la liste des utilisateurs impliqués.

Lorsque vous commencez à suivre des liens, un enfer de rappel peut commencer. Pour éviter cela, vous devez utiliser une sorte de promesses, de futurs ou autre. Je garde toujours asynchrone dans ma ceinture d'outils. Voici donc un exemple complet d'un robot utilisant async:

var
    url = require('url'),
    request = require('request'),
    async = require('async'),
    cheerio = require('cheerio');

var
    baseUrl = 'http://stackoverflow.com/';

// Gets a page and returns a callback with a $ object
function getPage(url, parseFn) {
    request({
        url: url
    }, function (error, response, body) {
        parseFn(cheerio.load(body))
    });
}

getPage(baseUrl, function ($) {
    var
        questions;

    // Get list of questions
    questions = $('.question-summary .question-hyperlink').map(function () {
        return {
            title: $(this).text(),
            url: url.resolve(baseUrl, $(this).attr('href'))
        };
    }).get().slice(0, 5); // limit to the top 5 questions

    // For each question
    async.map(questions, function (question, questionDone) {

        getPage(question.url, function ($$) {

            // Get list of users
            question.users = $$('.post-signature .user-details a').map(function () {
                return $$(this).text();
            }).get();

            questionDone(null, question);
        });

    }, function (err, questionsWithPosters) {

        // This function is called by async when all questions have been parsed

        questionsWithPosters.forEach(function (question) {

            // Prints each question along with its user list
            console.info(question.title);
            question.users.forEach(function (user) {
                console.info('\t%s', user);
            });
        });
    });
});

Avant de courir:

demande d'installation npm async cheerio

Exécutez un test:

node crawler.js

Exemple de sortie:

Is it possible to pause a Docker image build?
    conradk
    Thomasleveil
PHP Image Crop Issue
    Elyor
    Houston Molinar
Add two object in rails
    user1670773
    Makoto
    max
Asymmetric encryption discrepancy - Android vs Java
    Cookie Monster
    Wand Maker
Objective-C: Adding 10 seconds to timer in SpriteKit
    Christian K Rider

Et c'est la base que vous devez savoir pour commencer à créer vos propres robots :-)


Bibliothèques utilisées

Lucio Paiva
la source
22

en 2016, les choses sont beaucoup plus faciles. installez jquery sur node.js avec votre console:

npm install jquery

le lier à la variable $(par exemple - je suis habitué) dans votre code node.js:

var $ = require("jquery");

faire des trucs:

$.ajax({
    url: 'gimme_json.php',
    dataType: 'json',
    method: 'GET',
    data: { "now" : true }
});

fonctionne également pour gulp car il est basé sur node.js.

low_rents
la source
Quelle version de nœud utilisez-vous? Sur Mac, Node 6.10.2, jquery 2.2.4, var $ = require("jquery"); $.ajax // undefined (Downvoted for the moment).
AJP
@AJP et vous êtes sûr que vous l'avez fait en npm install jquerypremier?
low_rents
1
Oui. > console.log(require("jquery").toString());me donne la fonction d'usine: function ( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); } j'ai dû utiliser la réponse ci-dessus avec jsdom: stackoverflow.com/a/4129032/539490
AJP
@AJP ok, c'est étrange.
low_rents
J'obtiens exactement la même fonction d'usine que @AJP. Quelle version de jquery avez-vous utilisée, @low_rents?
Boris Burkov
18

Je crois que la réponse à cette question est maintenant oui.
https://github.com/tmpvar/jsdom

var navigator = { userAgent: "node-js" };  
var jQuery = require("./node-jquery").jQueryInit(window, navigator);
rdzah
la source
9
Je suis désolé de signaler qu'il va falloir plus de travail pour faire fonctionner jQuery sur jsdom. Sizzle fonctionne cependant! Je veux vraiment garder jsdom aussi léger que possible, donc ajouter une émulation de navigateur complète comme env.js n'est pas vraiment une priorité pour le moment.
tmpvar
peu importe, j'ai trouvé la copie modifiée fournie avec jsdom.
drewish
FYI node-jquery est désormais obsolète au profit de jquery
Ruslan López
1
ReferenceError: la fenêtre n'est pas définie
Bonn
17

npm install jquery --save #note TOUT EN MAJUSCULE

npm install jsdom --save

const jsdom = require("jsdom");
const dom = new jsdom.JSDOM(`<!DOCTYPE html>`);
var $ = require("jquery")(dom.window);


$.getJSON('https://api.github.com/users/nhambayi',function(data) {
  console.log(data);
});
Noé
la source
c'est la bonne réponse! pls upvote this
datdinhquoc
8

Le module jQuery peut être installé en utilisant:

npm install jquery

Exemple:

var $ = require('jquery');
var http = require('http');

var options = {
    host: 'jquery.com',
    port: 80,
    path: '/'
};

var html = '';
http.get(options, function(res) {
res.on('data', function(data) {
    // collect the data chunks to the variable named "html"
    html += data;
}).on('end', function() {
    // the whole of webpage data has been collected. parsing time!
    var title = $(html).find('title').text();
    console.log(title);
 });
});

Références de jQuery dans Node.js **:

SUNDARRAJAN K
la source
2
Ne fonctionne pas pour moi ... C: \ ... \\ node_modules \ jquery \ dist \ jquery.js: 31 jeter une nouvelle erreur ("jQuery nécessite une fenêtre avec un document"); ^ Erreur: jQuery nécessite une fenêtre avec un document à module.exports (C: \ ... \ WebContent \ resources \ js \ node_modules \ jquery \ dist \ jquery.js: 31: 12)
Jose Manuel Gomez Alvarez
var jsdom = require ("jsdom"); var window = jsdom.jsdom (). defaultView; jsdom.jQueryify (window, " code.jquery.com/jquery.js ", function () {var $ = window. $; $ ("body"). prepend ("<h1> Le titre </h1>") ; console.log ($ ("h1"). html ());});
SUNDARRAJAN K
7

Vous devez obtenir la fenêtre en utilisant la nouvelle API JSDOM.

const jsdom = require("jsdom");
const { window } = new jsdom.JSDOM(`...`);
var $ = require("jquery")(window);
UnchartedWorks
la source
le .JSDOM ( ...) devrait être .JSDOM ("<! DOCTYPE html>") pour la prise en charge HTML5?
datdinhquoc
2

ATTENTION

Cette solution, comme l'a mentionné Golo Roden, n'est pas correcte . C'est juste une solution rapide pour aider les gens à faire fonctionner leur code jQuery réel à l'aide d'une structure d'application Node, mais ce n'est pas la philosophie Node car le jQuery fonctionne toujours côté client plutôt que côté serveur. Je suis désolé d'avoir donné une mauvaise réponse.


Vous pouvez également rendre Jade avec un nœud et y mettre votre code jQuery. Voici le code du fichier jade:

!!! 5
html(lang="en")
  head
    title Holamundo!
    script(type='text/javascript', src='http://code.jquery.com/jquery-1.9.1.js')
  body
    h1#headTitle Hello, World
    p#content This is an example of Jade.
    script
      $('#headTitle').click(function() {
        $(this).hide();
      });
      $('#content').click(function() {
        $(this).hide();
      });
Timbergus
la source
4
Voté parce que la question indiquait explicitement qu'il s'agissait de jQuery côté serveur. En intégrant simplement jQuery dans un fichier jade, jQuery est toujours exécuté côté client. Par conséquent, cette réponse n'aide pas: - /
Golo Roden
2
D'accord, merci beaucoup. Je l'ai compris. Je vais essayer de le clarifier dans la réponse afin de ne pas confondre les personnes qui le lisent. Merci encore pour votre aide Golo.
Timbergus
2
Vous êtes les bienvenus :-). Et tant pis: nous faisons tous nos erreurs, alors ne vous inquiétez pas :-)
Golo Roden
2

Mon code de travail est:

npm install jquery

et alors:

global.jQuery   = require('jquery');
global.$        = global.jQuery;

ou si la fenêtre est présente, alors:

typeof window !== "undefined" ? window : this;
window.jQuery   = require('jquery');
window.$        = window.jQuery;
romain
la source
1

Le module jsdom est un excellent outil. Mais si vous voulez évaluer des pages entières et faire des trucs géniaux côté serveur, je vous suggère de les exécuter dans leur propre contexte:

vm.runInContext

Ainsi, des choses comme require/ CommonJSon site ne feront pas exploser votre processus Node lui-même.

Vous pouvez trouver la documentation ici . À votre santé!

Jakub Oboza
la source
1

Depuis jsdom v10, la fonction .env () est obsolète. Je l'ai fait comme ci-dessous après avoir essayé beaucoup de choses pour exiger jquery:

var jsdom = require('jsdom');
const { JSDOM } = jsdom;
const { window } = new JSDOM();
const { document } = (new JSDOM('')).window;
global.document = document;

var $ = jQuery = require('jquery')(window);

J'espère que cela vous aidera, vous ou toute personne confrontée à ce type de problèmes.

Plabon Dutta
la source
TypeError: JSDOM is not a constructor
Nathan Hawks
Si vous exécutez jQuery côté nœud, installez d'abord jquery et jsdom à l'aide de npm install. Ensuite, ajoutez les lignes ci-dessus dans le fichier dans lequel vous essayez d'utiliser le sélecteur jquery. Par exemple, j'ai utilisé un fichier $.each. Je viens d'inclure ces lignes, puis je l'ai fait comme ci-dessous: $.each(errors, function (ind,error) { res.send(error.msg);console.log(error.msg); }); J'espère que cela aide !!
Plabon Dutta
D'une manière ou d'une autre, jsdom avait décidé de ne pas installer du tout. Je suppose que je pense toujours à npm. Merci @
Nathan Hawks
0

Aucune de ces solutions ne m'a aidé dans mon application Electron.

Ma solution (solution de contournement):

npm install jquery

Dans votre index.jsdossier:

var jQuery = $ = require('jquery');

Dans vos .jsfichiers, écrivez vos fonctions jQuery de cette façon:

jQuery(document).ready(function() {
Elio Osés
la source
-1

Non. Ce sera un gros effort de porter un environnement de navigateur sur un nœud.

Une autre approche, que j'étudie actuellement pour les tests unitaires, consiste à créer une version "fictive" de jQuery qui fournit des rappels chaque fois qu'un sélecteur est appelé.

De cette façon, vous pouvez tester vos plugins jQuery sans avoir de DOM. Vous devrez toujours tester dans de vrais navigateurs pour voir si votre code fonctionne à l'état sauvage, mais si vous découvrez des problèmes spécifiques au navigateur, vous pouvez facilement "simuler" ceux de vos tests unitaires.

Je pousserai quelque chose sur github.com/felixge une fois qu'il sera prêt à être diffusé.

Felix Geisendörfer
la source
J'aime cette idée ... ça devrait être assez facile à faire.
Sudhir Jonathan
-1

Vous pouvez utiliser Electron , il autorise les browserjs hybrides et les nodejs.

Avant, j'essayais d'utiliser canvas2d dans nodejs, mais finalement j'ai abandonné. Il n'est pas pris en charge par nodejs par défaut, et trop difficile à installer (beaucoup de ... dépendances). Jusqu'à ce que j'utilise Electron, je peux facilement utiliser tout mon code de navigateur précédent, même WebGL, et transmettre la valeur du résultat (par exemple, les données d'image de base64 du résultat) au code nodejs.

gonnavis
la source
-9

Pas que je sache de. Le DOM est une chose côté client (jQuery n'analyse pas le HTML, mais le DOM).

Voici quelques projets Node.js en cours:

https://github.com/ry/node/wiki ( https://github.com/nodejs/node )

Et le djangode de SimonW est sacrément cool ...

Nosredna
la source
Je souhaite que ce soit possible. J'ai déjà essayé d'inclure jquery sur un projet node.js et bien sûr cela n'a pas fonctionné. jQuery est basé sur un document / une fenêtre. Rhino est capable d'exécuter le serveur jQuery: ejohn.org/blog/bringing-the-browser-to-the-server Je vais chercher plus d'analyseurs. Il y en a peut-être un qui ne dépend pas du navigateur.
John
@John: la seule raison pour laquelle jQuery peut s'exécuter sur Rhino est à cause de ce projet: github.com/jeresig/env-js/blob/master/src/env.js Il simule une petite partie du DOM et de l'exécution JavaScript. Il repose sur des API Java, donc c'est un no-go pour Node.js (qui utilise V8 / C ++).
Crescent Fresh
2
@Nosredna Bien que cela ait pu être vrai lorsque vous l'avez écrit, ce n'est clairement plus le cas. Je vous suggère de supprimer votre réponse maintenant.
Keith Pinson
-18

Une alternative consiste à utiliser Underscore.js . Il devrait fournir ce que vous auriez pu vouloir côté serveur de JQuery.

John Wright
la source
10
Peux-tu expliquer? jQuery fournit des tonnes d'API de manipulation / traversée / filtrage DOM. Le soulignement ressemble à des utilitaires de bibliothèque génériques n'ayant rien à voir avec le DOM.
Peter Lyons
1
Même chose ici, je ne vois pas en quoi cela est pertinent, les deux sont des compléments, pas des alternatives
Yi Jiang
2
Cette réponse n'est pas totalement fausse. jQuery et Underscore se chevauchent: ils fournissent tous deux des fonctionnalités telles que forEach.
tuomassalo
8
-1 Ils ont des fonctionnalités qui se chevauchent, mais Underscore n'est pas un remplacement jQuery.
Sam
2
La question se pose cependant sur la manipulation / les sélecteurs DOM.
mikermcneil