Posso usare jQuery con Node.js?


574

È possibile utilizzare i selettori jQuery / manipolazione DOM sul lato server utilizzando Node.js?


3
Mi chiedo: perché utilizzare sul lato server mentre è possibile farlo sul lato client?
Inanc Gumus,

31
Forse potresti voler creare un web scrapper che elimina informazioni specifiche a intervalli regolari e memorizza i risultati in un database? Questo non sarebbe pratico dal lato client.
Trevor,

2
Dovresti anche dare un'occhiata a phantomjs, che ti consente di emulare un lato server browser con motore V8.
Dimitri Kopriwa,

2
La manipolazione del DOM @deeperx sul lato server potrebbe essere utile quando si crea un crawler. Vedere questa risposta .
Lucio Paiva,

SÌ - dai un'occhiata a questa risposta - Preferisco questo rispetto all'utilizzo di cheerio, poiché hai la piena potenza del selettore jQuery.
monika mevenkamp,

Risposte:


563

Aggiornamento (27-giu-18) : sembra che ci sia stato un aggiornamento importante jsdomche fa sì che la risposta originale non funzioni più. Ho trovato questa risposta che spiega come usare jsdomora. Ho copiato il codice pertinente di seguito.

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

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

Nota: la risposta originale non menziona il fatto che sarà necessario installare jsdom anche usandonpm install jsdom

Aggiornamento (fine 2013) : il team ufficiale di jQuery ha finalmente assunto la gestione del jquerypacchetto su npm:

npm install jquery

Poi:

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


43
È possibile utilizzare jQuery ajax da node.js con quel modulo npm?
ajsie

22
Non si installa su Windows (senza lavoro significativo ), nel qual caso consiglierei il modulo Cheerio: matthewmueller.github.com/cheerio
Simon East

7
+1 per mostrare dove trovare npm :) la maggior parte delle persone ha la cattiva abitudine di menzionare cose come se dovessero essere un dato (buon senso)
Val

12
Questo ritorna require("...").env is not a function.
Banderi,

4
@Banderi stesso con me, qualche idea? l'errore:TypeError: require(...).env is not a function
coderInrRain

58

Sì, puoi, usando una libreria che ho creato chiamato 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);

20
Nota che nodeQuery sta effettivamente cambiando la pagina dell'utente in tempo reale, quindi è ancora più bello di quanto ci si possa aspettare.
alessioalex,

Stavo cercando qualcosa del genere quando sono inciampato qui ... Ho appena guardato i pacchetti di nodi nQuery e jquery e nQuery è stato aggiornato un anno fa, dove ieri era jquery ... nQuery non è più sviluppato? e jquery influisce sul lato client come fa nQuery? Qualcuno li ha provati entrambi forse?
Logan,

2
@Logan nQuery è praticamente solo jquery. la differenza è che il codice viene eseguito sul server e, anziché fornire il codice jquery al browser, esegue il codice sul server ed esegue in remoto la manipolazione del dom ai browser connessi. Si noti inoltre che nQuery era un progetto sperimentale e mentre accetterò richieste pull per correggere bug, non è mai stato creato per alcuno scopo o progetto specifico, quindi non ha avuto molti commit
Thomas Blobaum,

@ThomasBlobaum non funziona per me, errore: , express = Express.createServer();e TypeError: Express.createServer is not a functionqualche idea?
coderInrain

@ThomasBlobaum sembra che tu non abbia l'ultima versione di Express. Prova npm install --save expressnel prompt dei comandi.
Gilbert-V,

55

Al momento della stesura c'è anche il mantenuto Cheerio .

Implementazione veloce, flessibile e snella di core jQuery progettata appositamente per il server.


2
+1 per Cheerio. jsdom, d'altra parte, è davvero doloroso iniziare a funzionare su Windows.
Simon East

1
Cheerio può utilizzare eventi differiti e chiamate Ajax?
Hoffmann,

6
non supporta molti selettori come:gt(1)
chovy

1
Nella mia esperienza questo funziona meglio. È molto più veloce di JSDOM.
Jason Prawn,

1
@Hoffmann, ho passato un secondo a controllare i documenti per te. No non lo fa. Cheerio ha solo metodi relativi al DOM.
Denis,


34

Un semplice cingolato che utilizza Cheerio

Questa è la mia formula per creare un semplice crawler in Node.js. È il motivo principale per voler fare manipolazione DOM sul lato server e probabilmente è il motivo per cui sei arrivato qui.

Innanzitutto, utilizzare requestper scaricare la pagina da analizzare. Quando il download è completo, gestiscilo cheerioe inizia la manipolazione del DOM proprio come usando jQuery.

Esempio funzionante:

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/');

In questo esempio verranno stampate sulla console tutte le domande principali visualizzate nella home page di SO. Questo è il motivo per cui adoro Node.js e la sua community. Non potrebbe essere più facile di così :-)

Installa dipendenze:

npm installa richiesta cheerio

Ed esegui (supponendo che lo script sopra sia nel file crawler.js):

nodo crawler.js


Codifica

Alcune pagine avranno contenuti non inglesi in una determinata codifica e dovrai decodificarle UTF-8. Ad esempio, una pagina in portoghese brasiliano (o in qualsiasi altra lingua di origine latina) verrà probabilmente codificata ISO-8859-1(alias "latin1"). Quando è necessaria la decodifica, dico di requestnon interpretare il contenuto in alcun modo e invece di usarlo iconv-liteper fare il lavoro.

Esempio funzionante:

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/');

Prima di eseguire, installare le dipendenze:

npm installa richiesta iconv-lite cheerio

E poi finalmente:

nodo crawler.js


Link seguenti

Il prossimo passo sarebbe seguire i link. Supponi di voler elencare tutti i poster di ogni domanda principale su SO. Devi prima elencare tutte le domande principali (esempio sopra) e quindi inserire ciascun collegamento, analizzando la pagina di ciascuna domanda per ottenere l'elenco degli utenti coinvolti.

Quando inizi a seguire i collegamenti, può iniziare un inferno di richiamata . Per evitarlo, dovresti usare una sorta di promesse, futuri o altro. Tengo sempre asincrono nella cintura degli attrezzi. Quindi, ecco un esempio completo di un crawler che usa 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);
            });
        });
    });
});

Prima di correre:

npm install request async cheerio

Esegui un test:

nodo crawler.js

Uscita campione:

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

E questa è la base che dovresti sapere per iniziare a creare i tuoi crawler :-)


Librerie utilizzate


22

nel 2016 le cose sono molto più facili. installa jquery su node.js con la tua console:

npm install jquery

associarlo alla variabile $(ad esempio - ci sono abituato) nel codice node.js:

var $ = require("jquery");

fare cose:

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

funziona anche per gulp in quanto si basa su node.js.


Quale versione del nodo stai usando? Su Mac, nodo 6.10.2, jquery 2.2.4, var $ = require("jquery"); $.ajax // undefined (Downvoted per il momento).
AJP

@AJP e sei sicuro di averlo fatto per npm install jqueryprimo?
low_rents,

1
Sì. > console.log(require("jquery").toString());mi dà la funzione di fabbrica: function ( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); } ho dovuto usare la risposta di cui sopra con jsdom: stackoverflow.com/a/4129032/539490
AJP

@AJP ok, è strano.
low_rents,

Ottengo esattamente la stessa funzione di fabbrica di @AJP. Quale versione di jquery hai usato, @low_rents?
Boris Burkov,

18

Credo che la risposta a questo sia ora sì.
https://github.com/tmpvar/jsdom

var navigator = { userAgent: "node-js" };  
var jQuery = require("./node-jquery").jQueryInit(window, navigator);

9
Mi dispiace segnalare che ci vorrà più lavoro per far funzionare jQuery su jsdom. Sizzle tuttavia funziona! Voglio davvero mantenere jsdom il più leggero possibile, quindi aggiungere l'emulazione completa del browser come env.js non è davvero una priorità in questo momento.
tmpvar,

non importa, ho trovato la copia modificata inclusa in jsdom.
sorteggiato il

FYI node-jquery ora è deprecato a favore di jquery
Ruslan López

1
Errore di riferimento: la finestra non è definita
Bonn

17

npm install jquery --save #note TUTTO BASSO

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);
});

questa è la risposta chiara! per favore
vota

8

Il modulo jQuery può essere installato utilizzando:

npm install jquery

Esempio:

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);
 });
});

Riferimenti di jQuery in Node.js **:


2
Non funziona per me ... C: \ ... \\ node_modules \ jquery \ dist \ jquery.js: 31 genera un nuovo errore ("jQuery richiede una finestra con un documento"); ^ Errore: jQuery richiede una finestra con un documento su 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> The title </h1>") ; console.log ($ ("h1"). html ());});
SUNDARRAJAN K,

7

Devi ottenere la finestra usando la nuova API JSDOM.

const jsdom = require("jsdom");
const { window } = new jsdom.JSDOM(`...`);
var $ = require("jquery")(window);

.JSDOM ( ...) dovrebbe essere .JSDOM ("<! DOCTYPE html>") per il supporto HTML5?
datdinhquoc

2

AVVERTIMENTO

Questa soluzione, come menzionato da Golo Roden, non è corretta . È solo una soluzione rapida per aiutare le persone a far funzionare il proprio codice jQuery utilizzando una struttura dell'app Node, ma non è la filosofia Node perché jQuery è ancora in esecuzione sul lato client anziché sul lato server. Mi dispiace per aver dato una risposta sbagliata.


Puoi anche rendere Jade con il nodo e inserire il tuo codice jQuery. Ecco il codice del file 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();
      });

4
Sottovalutato perché la domanda affermava esplicitamente che si tratta di jQuery sul lato server. Semplicemente incorporando jQuery in un file jade jQuery viene ancora eseguito sul lato client. Quindi, questa risposta non aiuta: - /
Golo Roden,

2
Ok vi ringrazio molto. Ho capito. Cercherò di chiarirlo nella risposta per non confondere le persone che lo leggono. Grazie ancora per il tuo aiuto Golo.
Timbergus,

2
Prego :-). E non importa: facciamo tutti i nostri errori, quindi non preoccuparti :-)
Golo Roden,

2

Il mio codice di lavoro è:

npm install jquery

e poi:

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

o se la finestra è presente, quindi:

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

1

Il modulo jsdom è un ottimo strumento. Ma se vuoi valutare intere pagine e fare cose funky sul loro lato server, ti suggerisco di eseguirle nel loro contesto:

vm.runInContext

Quindi cose come require/ CommonJSsul posto non faranno esplodere il processo Node stesso.

Puoi trovare la documentazione qui . Saluti!


1

A partire da jsdom v10, la funzione .env () è obsoleta. L'ho fatto come di seguito dopo aver provato molte cose per richiedere 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);

Spero che questo aiuti te o chiunque abbia affrontato questo tipo di problemi.


TypeError: JSDOM is not a constructor
Nathan Hawks,

Se stai eseguendo jQuery sul lato nodo, per prima cosa installa jquery e jsdom usando npm install. Quindi, aggiungi le righe sopra nel file in cui stai tentando di utilizzare il selettore jquery. Ad esempio, ho usato un $.each. Ho appena incluso queste righe e poi l'ho fatto come di seguito: $.each(errors, function (ind,error) { res.send(error.msg);console.log(error.msg); }); spero che questo aiuti !!
Plabon Dutta,

In qualche modo jsdom aveva deciso di non installarlo affatto. Immagino che sto ancora cercando di capire npm. Grazie @
Nathan Hawks il


0

Nessuna di queste soluzioni mi ha aiutato nella mia app Electron.

La mia soluzione (soluzione alternativa):

npm install jquery

Nel tuo index.jsfile:

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

Nei tuoi .jsfile scrivi le tue funzioni jQuery in questo modo:

jQuery(document).ready(function() {


-1

No. Sarà un grande sforzo per trasferire un ambiente browser sul nodo.

Un altro approccio, che sto attualmente indagando per i test unitari, è quello di creare la versione "Mock" di jQuery che fornisce i callback ogni volta che viene chiamato un selettore.

In questo modo potresti testare l'unità dei tuoi plugin jQuery senza avere effettivamente un DOM. Dovrai comunque testare nei browser reali per vedere se il tuo codice funziona in modo selvaggio, ma se scopri problemi specifici del browser, puoi facilmente "deridere" anche quelli nei tuoi test unitari.

Spingerò qualcosa su github.com/felixge una volta che è pronto per essere mostrato.


Mi piace questa idea ... dovrebbe essere abbastanza facile da fare.
Sudhir Jonathan,

-1

È possibile utilizzare Electron , consente browserjs ibridi e nodejs.

Prima, ho provato ad usare canvas2d in nodejs, ma alla fine ho rinunciato. Non è supportato per impostazione predefinita da nodejs e troppo difficile da installarlo (molti molti ... dipendenti). Fino a quando non utilizzo Electron, posso facilmente utilizzare tutto il mio precedente codice browserjs, anche WebGL, e passare il valore del risultato (ad es. I dati immagine base64 del risultato) al codice nodejs.


-9

Non che io sappia. Il DOM è una cosa lato client (jQuery non analizza l'HTML, ma il DOM).

Ecco alcuni progetti Node.js attuali:

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

E il djangode di SimonW è dannatamente bello ...


Vorrei che fosse possibile. Ho già provato a includere jquery in un progetto node.js e ovviamente non ha funzionato. jQuery si basa sul documento / finestra. Rhino è in grado di eseguire il lato server jQuery: ejohn.org/blog/bringing-the-browser-to-the-server Ho intenzione di cercare altri parser. Forse ce n'è uno che non dipende dal browser.
Giovanni,

@John: l'unica ragione per cui jQuery può essere eseguito su Rhino è a causa di questo progetto: github.com/jeresig/env-js/blob/master/src/env.js Simula una piccola porzione del DOM e del runtime JavaScript. Si basa su API Java, quindi è un no-go per Node.js (che utilizza V8 / C ++).
Crescent Fresh,

2
@Nosredna Anche se questo potrebbe essere vero quando l'hai scritto, chiaramente non è più vero. Ti suggerisco di eliminare la tua risposta ora.
Keith Pinson,

-18

Un'alternativa è usare Underscore.js . Dovrebbe fornire ciò che avresti potuto desiderare sul lato server da JQuery.


10
Puoi spiegare? jQuery fornisce tonnellate di API di manipolazione / attraversamento / filtro DOM. Il carattere di sottolineatura assomiglia a utility di libreria generiche che non hanno nulla a che fare con il DOM.
Peter Lyons,

1
Lo stesso qui, non vedo quanto questo sia rilevante, i due sono complementi, non alternative
Yi Jiang,

2
Questa risposta non è totalmente sbagliata. jQuery e Underscore si sovrappongono: entrambi forniscono funzionalità come forEach.
tuomassalo,

8
-1 Hanno funzionalità sovrapposte ma Underscore non è un sostituto di jQuery.
Sam,

2
Tuttavia, la domanda è sulla manipolazione / selettori DOM.
mikermcneil,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.