Posso usar jQuery com Node.js?

574

É possível usar a seleção de jQuery / manipulação DOM no lado do servidor usando o Node.js.

John
fonte
3
Eu me pergunto: por que usar no lado do servidor enquanto você pode fazê-lo no lado do cliente?
Inanc Gumus
31
Talvez você queira criar um web scrapper que recolhe informações específicas em intervalos regulares e armazena os resultados em um banco de dados? Isso não seria tão prático do lado do cliente.
Trevor
2
Você também deve dar uma olhada nos phantomjs, que permitem emular um lado do servidor do navegador com o mecanismo V8.
Dimitri Kopriwa
2
A manipulação DOM do @deeperx no lado do servidor pode ser útil ao criar um rastreador. Veja esta resposta .
Lucio Paiva
SIM - dê uma olhada nesta resposta - eu prefiro isso usando cheerio, pois você obtém todo o poder do seletor jQuery.
monika mevenkamp 22/01

Respostas:

563

Atualização (27-jun-18) : Parece que houve uma grande atualização jsdomque faz com que a resposta original não funcione mais. Encontrei esta resposta que explica como usar jsdomagora. Copiei o código relevante abaixo.

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: A resposta original não menciona que você precisará instalar o jsdom também usandonpm install jsdom

Atualização (final de 2013) : A equipe oficial do jQuery finalmente assumiu o gerenciamento do jquerypacote no npm:

npm install jquery

Então:

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

Philippe Rathé
fonte
43
É possível usar o jQuery ajax do node.js com esse módulo npm?
ajsie
22
Não instalar no Windows (sem significativa de trabalho), caso em que eu recomendaria o módulo Cheerio: matthewmueller.github.com/cheerio
Simon Médio
7
+1 para mostrar onde obter npm :) a maioria das pessoas têm o mau hábito de apenas mencionar coisas como se deve ser um dado (o senso comum)
Val
12
Isso retorna require("...").env is not a function.
28417 Banderi
4
@Banderi mesmo comigo, alguma idéia? o erro:TypeError: require(...).env is not a function
coderInrRain 08/08
58

Sim, você pode, usando uma biblioteca que criei chamada 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
fonte
20
Observe que o nodeQuery está realmente alterando a página do usuário em tempo real, portanto é ainda mais interessante do que se poderia esperar.
Alessioalex
Eu estava procurando algo assim quando tropecei aqui ... Acabei de examinar os pacotes nQuery e jquery node e o nQuery foi atualizado há um ano onde jquery estava ontem ... O nQuery não está mais desenvolvido? e o jquery afeta o lado do cliente como o nQuery? Alguém já tentou os dois, talvez?
Logan
2
@Logan nQuery é basicamente apenas jquery. a diferença é que o código é executado no servidor e, em vez de fornecer o código jquery ao navegador, ele executa o código no servidor e executa remotamente a manipulação do dom nos navegadores conectados. Observe também que nQuery era um projeto experimental, e enquanto eu aceitará solicitações de pull para fixar bugs, nunca foi criado para qualquer finalidade ou projeto específico para que ele não teve muitos commits
Thomas Blobaum
@ThomasBlobaum não está funcionando para mim, erro: , express = Express.createServer();e TypeError: Express.createServer is not a functionalguma idéia?
CodigoInrRain
@ThomasBlobaum parece que você não possui a versão mais recente do Express. Tente npm install --save expressno seu prompt de comando.
gilbert-v
55

No momento em que escrevo, também existe o Cheerio mantido .

Implementação rápida, flexível e enxuta do jQuery principal, projetado especificamente para o servidor.

Alfred
fonte
2
+1 para Cheerio. jsdom, por outro lado, é realmente doloroso ao rodar no Windows.
Simon East
1
A Cheerio pode usar eventos adiados e chamadas ajax?
Hoffmann
6
não suporta uma grande quantidade de seletores como:gt(1)
Chovy
1
Na minha experiência, este funciona melhor. É muito mais rápido que o JSDOM.
Jason Prawn
1
@Hoffmann, passei um segundo para verificar os documentos para você. Não, não tem. Cheerio possui apenas métodos relacionados ao DOM.
Denis
39

Agora, usando jsdom, você pode. Veja o exemplo de jquery no diretório examples.

Benjamin Coe
fonte
Uma desvantagem do jQueryify () de jsdom é que ele executa todos os scripts da página.
261
e ele não funciona no Windows sem muita dor de cabeça
Jason Goemaat
1
em 2016 você não precisa jsdom mais - veja minha resposta: stackoverflow.com/a/40656811/3391783
low_rents
34

Um rastreador simples usando Cheerio

Esta é minha fórmula para criar um rastreador simples no Node.js. É o principal motivo para querer manipular o DOM no servidor e, provavelmente, é o motivo pelo qual você chegou aqui.

Primeiro, use requestpara baixar a página a ser analisada. Quando o download estiver concluído, manipule-o cheerioe inicie a manipulação do DOM, assim como o jQuery.

Exemplo de trabalho:

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 exemplo imprimirá no console todas as principais perguntas exibidas na home page do SO. É por isso que eu amo o Node.js e sua comunidade. Não poderia ficar mais fácil do que isso :-)

Instale dependências:

solicitação de instalação npm cheerio

E execute (assumindo que o script acima esteja no arquivo crawler.js):

nó crawler.js


Codificação

Algumas páginas terão conteúdo em inglês em uma determinada codificação e você precisará decodificá-lo UTF-8. Por exemplo, uma página em português do Brasil (ou qualquer outro idioma de origem latina) provavelmente será codificada em ISO-8859-1(aka "latin1"). Quando a decodificação é necessária, digo requestpara não interpretar o conteúdo de nenhuma maneira e, em vez disso, uso iconv-litepara fazer o trabalho.

Exemplo de trabalho:

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 executar, instale dependências:

solicitação de instalação do npm iconv-lite cheerio

E finalmente:

nó crawler.js


Links a seguir

O próximo passo seria seguir os links. Digamos que você queira listar todos os pôsteres de cada pergunta principal no SO. Você deve primeiro listar todas as perguntas principais (exemplo acima) e depois inserir cada link, analisando a página de cada pergunta para obter a lista de usuários envolvidos.

Quando você começa a seguir os links, um inferno de retorno de chamada pode começar. Para evitar isso, você deve usar algum tipo de promessas, futuros ou o que for. Eu sempre assíncrono no meu cinto de ferramentas. Então, aqui está um exemplo completo de um rastreador usando assí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 executar:

solicitação de instalação npm assíncrona cheerio

Execute um teste:

nó crawler.js

Saída de amostra:

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 esse é o básico que você deve saber para começar a criar seus próprios rastreadores :-)


Bibliotecas usadas

Lucio Paiva
fonte
22

em 2016 as coisas são muito mais fáceis. instale o jquery no node.js com seu console:

npm install jquery

vincule-o à variável $(por exemplo - eu estou acostumado) no código node.js:

var $ = require("jquery");

Fazer coisas:

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

também funciona para o gulp, pois é baseado no node.js.

low_rents
fonte
Qual versão do nó você está usando? No Mac, nó 6.10.2, jquery 2.2.4, var $ = require("jquery"); $.ajax // undefined (com voto negativo no momento).
AJP
@AJP e você tem certeza de que fez npm install jqueryprimeiro?
Low_rents
1
Sim. > console.log(require("jquery").toString());dá-me a função de fábrica: function ( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); } eu tive que usar a resposta acima com jsdom: stackoverflow.com/a/4129032/539490
AJP
@ AJJ ok, isso é estranho.
Low_rents
Recebo exatamente a mesma função de fábrica que a @AJP. Qual versão do jquery você usou, @low_rents?
Boris Burkov
18

Eu acredito que a resposta para isso é agora sim.
https://github.com/tmpvar/jsdom

var navigator = { userAgent: "node-js" };  
var jQuery = require("./node-jquery").jQueryInit(window, navigator);
rdzah
fonte
9
Lamento informar que será necessário mais trabalho para executar o jQuery no jsdom. Chiar no entanto funciona! Eu realmente quero manter o jsdom o mais leve possível, portanto, adicionar emulação de navegador completa como env.js não é realmente uma prioridade no momento.
Tmpvar
não importa, encontrei a cópia modificada que acompanha o jsdom.
drewish
FYI nó-jquery está obsoleta agora em favor de jquery
Ruslan López
1
ReferenceError: janela não é definido
Bonn
17

npm install jquery --save #note TUDO EM BAIXO

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é
fonte
esta é a resposta legal! pls
votou positivamente
8

O módulo jQuery pode ser instalado usando:

npm install jquery

Exemplo:

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

Referências do jQuery no Node.js **:

SUNDARRAJAN K
fonte
2
Não funciona para mim ... C: \ ... \\ node_modules \ jquery \ dist \ jquery.js: 31 throw new Error ("o jQuery requer uma janela com um documento"); ^ Erro: o jQuery requer uma janela com um documento em module.exports (C: \ ... \ WebContent \ resources \ js \ node_modules \ jquery \ dist \ jquery.js: 31: 12)
Jose Manuel Gomez Alvarez,
var jsdom = require ("jsdom"); var janela = jsdom.jsdom (). defaultView; jsdom.jQueryify (window, " code.jquery.com/jquery.js ", function () {var $ = window. $; $ ("body"). prepend ("<h1> O título </h1>") ; console.log ($ ("h1"). html ());});
SUNDARRAJAN K
7

Você deve obter a janela usando a nova API JSDOM.

const jsdom = require("jsdom");
const { window } = new jsdom.JSDOM(`...`);
var $ = require("jquery")(window);
UnchartedWorks
fonte
o .JSDOM ( ...) deve ser .JSDOM ("<! DOCTYPE html>") para suporte ao HTML5?
datdinhquoc 29/01
2

ATENÇÃO

Esta solução, como mencionado por Golo Roden, não está correta . É apenas uma solução rápida para ajudar as pessoas a executar o código jQuery real usando uma estrutura de aplicativo Node, mas não é a filosofia do Node porque o jQuery ainda está sendo executado no lado do cliente e não no lado do servidor. Sinto muito por dar uma resposta errada.


Você também pode renderizar o Jade com o nó e inserir seu código jQuery. Aqui está o código do arquivo 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
fonte
4
Voto negativo porque a pergunta afirmou explicitamente que se trata de jQuery no lado do servidor. Simplesmente incorporando o jQuery em um arquivo jade, o jQuery ainda é executado no lado do cliente. Portanto, esta resposta não ajuda: - /
Golo Roden
2
Ok, muito obrigado. Eu entendo isso. Vou tentar esclarecê-lo na resposta para não confundir as pessoas que o lêem. Mais uma vez obrigado pela sua ajuda Golo.
Timbergus 31/05
2
De nada :-). E não importa: Todos nós cometemos nossos erros, então não se preocupe :-)
Golo Roden
2

Meu código de trabalho é:

npm install jquery

e depois:

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

ou se a janela estiver presente, então:

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

O módulo jsdom é uma ótima ferramenta. Mas se você deseja avaliar páginas inteiras e fazer algumas coisas divertidas no lado do servidor, sugiro executá-las em seu próprio contexto:

vm.runInContext

Portanto, coisas como require/ CommonJSno site não afetarão o processo do Node.

Você pode encontrar documentação aqui . Felicidades!

Jakub Oboza
fonte
1

A partir do jsdom v10, a função .env () está obsoleta. Fiz isso como abaixo, depois de tentar várias coisas para exigir o 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 isso ajude você ou qualquer pessoa que esteja enfrentando esse tipo de problema.

Plabon Dutta
fonte
TypeError: JSDOM is not a constructor
Nathan Hawks
Se você estiver executando o jQuery no lado do Node, primeiro instale o jquery e o jsdom usando o npm install. Em seguida, adicione linhas acima no arquivo em que você está tentando usar o seletor jquery. Por exemplo, eu usei a $.each. Eu apenas incluí estas linhas e depois fiz o seguinte: $.each(errors, function (ind,error) { res.send(error.msg);console.log(error.msg); }); Espero que ajude !!
Plabon Dutta 31/12/19
De alguma forma, o jsdom decidiu não instalar. Acho que ainda estou descobrindo o NPM. Obrigado @
Nathan Hawks
0

Nenhuma dessas soluções me ajudou no meu aplicativo Electron.

Minha solução (solução alternativa):

npm install jquery

No seu index.jsarquivo:

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

Nos seus .jsarquivos, escreva suas funções jQuery desta maneira:

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

Não. Será um grande esforço portar um ambiente de navegador para o nó.

Outra abordagem, que estou investigando atualmente para testes de unidade, é criar a versão "Mock" do jQuery que fornece retornos de chamada sempre que um seletor é chamado.

Dessa forma, você poderia testar seus plugins jQuery sem realmente ter um DOM. Você ainda precisará testar em navegadores reais para ver se seu código funciona de maneira natural, mas se descobrir problemas específicos do navegador, poderá facilmente "zombar" daqueles dos testes de unidade.

Vou empurrar algo para o github.com/felixge assim que estiver pronto para ser exibido.

Felix Geisendörfer
fonte
Eu gosto dessa idéia ... deve ser bem fácil de fazer.
Sudhir Jonathan
-1

Você pode usar o Electron , ele permite que o navegador híbridojs e nodejs.

Antes, tentei usar o canvas2d no nodejs, mas finalmente desisti. Não é suportado pelo padrão nodejs, e é muito difícil de instalá-lo (muitos ... dependentes). Até usar o Electron, posso facilmente usar todo o meu código anterior do navegadorjs, até o WebGL, e passar o valor do resultado (por exemplo, dados da imagem do resultado base64) para o código do nodejs.

gonnavis
fonte
-9

Não que eu saiba. O DOM é uma coisa do lado do cliente (o jQuery não analisa o HTML, mas o DOM).

Aqui estão alguns projetos atuais do Node.js.

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

E o djangode do SimonW é bem legal ...

Nosredna
fonte
Eu gostaria que fosse possível. Eu já tentei incluir o jquery em um projeto node.js e, é claro, não funcionou. O jQuery é baseado em documento / janela. O Rhino é capaz de executar o lado do servidor jQuery: ejohn.org/blog/bringing-the-browser-to-the-server Vou procurar mais analisadores. Talvez haja um que não dependa do navegador.
John
@ John: a única razão pela qual o jQuery pode ser executado no Rhino é por causa deste projeto: github.com/jeresig/env-js/blob/master/src/env.js Ele simula uma pequena parte do DOM e do tempo de execução do JavaScript. Ele conta com APIs Java, assim como um Node.js (que usa V8 / C ++).
Crescent Fresh
2
@Nosredna Embora isso possa ter sido verdade quando você o escreveu, claramente não é mais verdade. Sugiro que você exclua sua resposta agora.
precisa
-18

Uma alternativa é usar Underscore.js . Ele deve fornecer o que você poderia querer do lado do servidor do JQuery.

John Wright
fonte
10
Você pode explicar? O jQuery fornece toneladas de APIs de manipulação / deslocamento / filtragem de DOM. Sublinhado parece utilitários de biblioteca genéricos que não têm nada a ver com o DOM.
Peter Lyons
1
Mesmo aqui, eu não vejo como isso é relevante os dois são complementares, e não alternativas
Yi Jiang
2
Esta resposta não está totalmente errada. O jQuery e o Underscore se sobrepõem: ambos fornecem recursos como o forEach.
tuomassalo 9/09/11
8
-1 Eles têm funcionalidade sobreposta, mas o Underscore não é um substituto do jQuery.
Sam
2
A questão é perguntar sobre a manipulação / seletores de DOM.
Mckmcneil