¿Puedo usar jQuery con Node.js?


574

¿Es posible usar selectores jQuery / manipulación DOM en el lado del servidor usando Node.js?


3
Me pregunto: ¿por qué usarlo en el lado del servidor mientras que puedes hacerlo en el lado del cliente?
Inanc Gumus

31
¿Quizás desee crear un scrapper web que elimine información específica a intervalos regulares y almacene los resultados en una base de datos? Esto no sería tan práctico desde el lado del cliente.
Trevor

2
También debe echar un vistazo a phantomjs, que le permiten emular un lado del servidor del navegador con el motor V8.
Dimitri Kopriwa

2
La manipulación DOM @deeperx en el lado del servidor podría ser útil al hacer un rastreador. Mira esta respuesta .
Lucio Paiva

SÍ, eche un vistazo a esta respuesta . Prefiero esto en lugar de usar cheerio, ya que obtiene toda la potencia del selector jQuery.
monika mevenkamp

Respuestas:


563

Actualización (27-jun-18) : Parece que hubo una actualización importante jsdomque hace que la respuesta original ya no funcione. Encontré esta respuesta que explica cómo usar jsdomahora. Copié el código relevante a continuación.

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 respuesta original no menciona que también necesitará instalar jsdom usandonpm install jsdom

Actualización (finales de 2013) : el equipo oficial de jQuery finalmente se hizo cargo de la administración del jquerypaquete en npm:

npm install jquery

Entonces:

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


43
¿Es posible usar jQuery ajax de node.js con ese módulo npm?
ajsie

22
No se instala en Windows (sin un trabajo significativo ), en cuyo caso recomendaría el módulo Cheerio: matthewmueller.github.com/cheerio
Simon East

77
+1 por mostrar dónde obtener npm :) la mayoría de la gente tiene la mala costumbre de mencionar cosas como si fuera un hecho (sentido común)
Val

12
Esto vuelve require("...").env is not a function.
Banderi

44
@Banderi igual conmigo, ¿alguna idea? el error:TypeError: require(...).env is not a function
coderInrRain

58

Sí, puedes, usando una biblioteca que creé llamada 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
Tenga en cuenta que nodeQuery en realidad está cambiando la página del usuario en tiempo real, por lo que es aún más genial de lo que cabría esperar.
alessioalex

Estaba buscando algo como esto cuando tropecé aquí ... Acabo de mirar los paquetes de nQuery y jquery node y nQuery se actualizó hace un año donde estaba jquery ayer ... ¿Ya no se desarrolla nQuery? y jquery afecta al lado del cliente como nQuery? ¿Alguien ha probado los dos tal vez?
Logan

2
@Logan nQuery es básicamente solo jquery. la diferencia es que el código se ejecuta en el servidor y, en lugar de entregar el código jquery al navegador, ejecuta el código en el servidor y ejecuta de forma remota la manipulación dom en los navegadores conectados. También tenga en cuenta que nQuery fue un proyecto experimental, y aunque aceptaré solicitudes de extracción para corregir errores, nunca se creó para ningún propósito o proyecto específico, por lo que no ha tenido muchos compromisos
Thomas Blobaum,

@ThomasBlobaum no funciona para mí, error: ¿ , express = Express.createServer();y TypeError: Express.createServer is not a functionalguna idea?
coderInrRain

@ThomasBlobaum parece que no tienes la última versión de Express. Intente npm install --save expressen su símbolo del sistema.
gilbert-v

55

Al momento de escribir también existe el Cheerio mantenido .

Implementación rápida, flexible y eficiente de Core jQuery diseñado específicamente para el servidor.


2
+1 para Cheerio. jsdom, por otro lado, es realmente doloroso para ejecutarse en Windows.
Simon East

1
¿Puede Cheerio usar eventos diferidos y llamadas ajax?
Hoffmann

66
no es compatible con muchos selectores como:gt(1)
chovy

1
En mi experiencia, este funciona mejor. Es mucho más rápido que JSDOM.
Jason Prawn

1
@ Hoffmann, pasé un segundo para revisar los documentos por ti. No, no lo hace. Cheerio solo tiene métodos relacionados con DOM.
Denis


34

Un rastreador simple que usa Cheerio

Esta es mi fórmula para hacer un rastreador simple en Node.js. Es la razón principal para querer hacer la manipulación DOM en el lado del servidor y probablemente es la razón por la que llegó aquí.

Primero, use requestpara descargar la página a analizar. Cuando se complete la descarga, manipúlela cheerioy comience a manipular DOM al igual que con jQuery.

Ejemplo de trabajo:

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

Este ejemplo imprimirá en la consola todas las preguntas principales que se muestran en la página de inicio de SO. Es por eso que amo a Node.js y su comunidad. No podría ser más fácil que eso :-)

Instalar dependencias:

solicitud de instalación de npm cheerio

Y ejecute (suponiendo que el script anterior esté en el archivo crawler.js):

nodo crawler.js


Codificación

Algunas páginas tendrán contenido que no esté en inglés en una determinada codificación y deberá decodificarlo UTF-8. Por ejemplo, una página en portugués brasileño (o cualquier otro idioma de origen latino) probablemente se codificará en ISO-8859-1(también conocido como "latin1"). Cuando se necesita decodificación, le digo que requestno interprete el contenido de ninguna manera y en su lugar lo uso iconv-litepara hacer el trabajo.

Ejemplo de trabajo:

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

Antes de ejecutar, instale dependencias:

solicitud de instalación de npm iconv-lite cheerio

Y luego finalmente:

nodo crawler.js


Enlaces siguientes

El siguiente paso sería seguir los enlaces. Digamos que desea enumerar todos los carteles de cada pregunta principal en SO. Primero debe enumerar todas las preguntas principales (ejemplo anterior) y luego ingresar cada enlace, analizando la página de cada pregunta para obtener la lista de usuarios involucrados.

Cuando comienzas a seguir enlaces, puede comenzar un infierno de devolución de llamada . Para evitar eso, debe usar algún tipo de promesas, futuros o lo que sea. Siempre mantengo asíncrono en mi cinturón de herramientas. Entonces, aquí hay un ejemplo completo de un rastreador que usa asíncrono:

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

Antes de correr:

npm solicitud de instalación async cheerio

Ejecute una prueba:

nodo crawler.js

Salida de muestra:

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

Y eso es lo básico que debes saber para comenzar a hacer tus propios rastreadores :-)


Bibliotecas utilizadas


22

en 2016 las cosas son mucho más fáciles. instale jquery a node.js con su consola:

npm install jquery

vincúlelo a la variable $(por ejemplo, estoy acostumbrado) en su código node.js:

var $ = require("jquery");

hacer cosas:

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

también funciona para tragar, ya que se basa en node.js.


¿Qué versión de nodo estás usando? En Mac, Nodo 6.10.2, jquery 2.2.4, var $ = require("jquery"); $.ajax // undefined (Votado por el momento).
AJP

@AJP y ¿estás seguro de que lo hiciste npm install jqueryprimero?
low_rents

1
Si. > console.log(require("jquery").toString());me da la función de fábrica: function ( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); } tuve que usar la respuesta anterior con jsdom: stackoverflow.com/a/4129032/539490
AJP

@AJP ok, eso es extraño.
low_rents

Obtengo exactamente la misma función de fábrica que @AJP. ¿Qué versión de jquery usaste, @low_rents?
Boris Burkov

18

Creo que la respuesta a esto es ahora sí.
https://github.com/tmpvar/jsdom

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

99
Lamento informar que tomará más trabajo hacer que jQuery se ejecute en jsdom. Sizzle sin embargo funciona! Realmente quiero mantener jsdom lo más ligero posible, por lo que agregar una emulación completa del navegador como env.js no es realmente una prioridad en este momento.
tmpvar

No importa, encontré la copia modificada que se incluye con jsdom.
2012

FYI node-jquery ahora está en desuso a favor de jquery
Ruslan López

1
ReferenceError: la ventana no está definida
Bonn

17

npm install jquery --save #note TODAS LAS MINÚSCULAS

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

esta es la buena respuesta! por favor vota esto
datdinhquoc

8

El módulo jQuery se puede instalar usando:

npm install jquery

Ejemplo:

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

Referencias de jQuery en Node.js **:


2
No me funciona ... C: \ ... \\ node_modules \ jquery \ dist \ jquery.js: 31 arroja un nuevo error ("jQuery requiere una ventana con un documento"); ^ Error: jQuery requiere una ventana con un documento en module.exports (C: \ ... \ WebContent \ resources \ js \ node_modules \ jquery \ dist \ jquery.js: 31: 12)
Jose Manuel Gomez Alvarez

var jsdom = require ("jsdom"); var ventana = 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

Debe obtener la ventana utilizando la nueva API JSDOM.

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

el .JSDOM ( ...) debe ser .JSDOM ("<! DOCTYPE html>") para soporte HTML5?
datdinhquoc

2

ADVERTENCIA

Esta solución, como mencionó Golo Roden, no es correcta . Es solo una solución rápida para ayudar a las personas a tener su código jQuery real ejecutándose usando una estructura de aplicación Node, pero no es una filosofía Node porque jQuery todavía se ejecuta en el lado del cliente en lugar del lado del servidor. Lo siento por dar una respuesta incorrecta.


También puede renderizar Jade con nodo y poner su código jQuery dentro. Aquí está el código del archivo 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();
      });

44
Voto negativo porque la pregunta explícitamente indica que se trata de jQuery en el lado del servidor. Simplemente incrustando jQuery en un archivo jade, jQuery todavía se ejecuta en el lado del cliente. Por lo tanto, esta respuesta no ayuda: - /
Golo Roden

2
Vale, muchas gracias. Lo he entendido Intentaré aclararlo en la respuesta para no confundir a las personas que lo leen. Gracias de nuevo por tu ayuda, Golo.
Timbergus

2
De nada :-). Y no importa: todos cometemos nuestros errores, así que no te preocupes :-)
Golo Roden

2

Mi código de trabajo es:

npm install jquery

y entonces:

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

o si la ventana está presente, entonces:

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

1

El módulo jsdom es una gran herramienta. Pero si desea evaluar páginas enteras y hacer algunas cosas funky en el lado del servidor, sugiero ejecutarlas en su propio contexto:

vm.runInContext

Así que cosas como require/ CommonJSen el sitio no arruinarán su proceso de Nodo en sí.

Puede encontrar documentación aquí . ¡Salud!


1

A partir de jsdom v10, la función .env () está en desuso. Lo hice como a continuación después de probar muchas cosas para requerir 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);

Espero que esto te ayude a ti o a cualquiera que haya enfrentado este tipo de problemas.


TypeError: JSDOM is not a constructor
Nathan Hawks

Si está ejecutando jQuery en el lado del nodo, en primer lugar, instale jquery y jsdom usando npm install. Luego, agregue las líneas anteriores en el archivo en el que está tratando de usar jquery selector. Por ejemplo, usé a $.each. Solo incluí estas líneas y luego lo hice a continuación: ¡ $.each(errors, function (ind,error) { res.send(error.msg);console.log(error.msg); }); Espero que esto ayude!
Plabon Dutta

De alguna manera, jsdom había decidido no instalarlo en absoluto. Supongo que todavía estoy descubriendo npm. Gracias @
Nathan Hawks


0

Ninguna de estas soluciones me ha ayudado en mi aplicación Electron.

Mi solución (solución alternativa):

npm install jquery

En tu index.jsarchivo:

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

En sus .jsarchivos, escriba las funciones de jQuery de esta manera:

jQuery(document).ready(function() {


-1

No. Será un gran esfuerzo portar un entorno de navegador al nodo.

Otro enfoque, que actualmente estoy investigando para pruebas unitarias, es crear una versión "simulada" de jQuery que proporcione devoluciones de llamada cada vez que se llame a un selector.

De esta manera, podría probar sus complementos jQuery sin tener un DOM. Todavía tendrá que probar en navegadores reales para ver si su código funciona en la naturaleza, pero si descubre problemas específicos del navegador, también puede "burlarse" de ellos en las pruebas de su unidad.

Enviaré algo a github.com/felixge una vez que esté listo para mostrar.


Me gusta esta idea ... debería ser bastante fácil de hacer.
Sudhir Jonathan

-1

Puede usar Electron , permite navegadores híbridos y nodos.

Antes, traté de usar canvas2d en nodejs, pero finalmente me di por vencido. No es compatible con el valor predeterminado de nodejs, y es demasiado difícil de instalar (muchas, muchas ... dependencias). Hasta que use Electron, puedo usar fácilmente todo mi código de navegador anterior, incluso WebGL, y pasar el valor del resultado (por ejemplo, datos de imagen de resultado base64) al código de nodo.


-9

No que yo sepa. El DOM es una cosa del lado del cliente (jQuery no analiza el HTML, sino el DOM).

Aquí hay algunos proyectos actuales de Node.js:

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

Y el djangode de SimonW es bastante genial ...


Desearía que fuera posible. Ya intenté incluir jquery en un proyecto node.js y, por supuesto, no funcionó. jQuery se basa en documento / ventana. Rhino es capaz de ejecutar el lado del servidor jQuery: ejohn.org/blog/bringing-the-browser-to-the-server Voy a buscar más analizadores. Quizás haya uno que no dependa del navegador.
John

@John: la única razón por la que jQuery puede ejecutarse en Rhino es por este proyecto: github.com/jeresig/env-js/blob/master/src/env.js Simula una pequeña porción del DOM y el tiempo de ejecución de JavaScript. Se basa en apis de Java, por lo que es un no-go para Node.js (que usa V8 / C ++).
Crescent Fresh el

2
@Nosredna Si bien esto puede haber sido cierto cuando lo escribió, claramente ya no es cierto. Le sugiero que elimine su respuesta ahora.
Keith Pinson

-18

Una alternativa es usar Underscore.js . Debería proporcionar lo que podría haber deseado del lado del servidor de JQuery.


10
¿Puedes explicar? jQuery proporciona toneladas de API DOM de manipulación / desplazamiento / filtrado. El subrayado parece utilidades genéricas de la biblioteca que no tienen nada que ver con el DOM.
Peter Lyons

1
Lo mismo aquí, no veo cómo esto es relevante, los dos son complementos, no alternativas
Yi Jiang

2
Esta respuesta no es totalmente incorrecta. jQuery y Underscore se superponen: ambos proporcionan características como forEach.
tuomassalo

8
-1 Tienen una funcionalidad superpuesta, pero el subrayado no es un reemplazo de jQuery.
Sam

2
Sin embargo, la pregunta es acerca de la manipulación / selectores DOM.
mikermcneil
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.