Bisakah saya menggunakan jQuery dengan Node.js?

574

Apakah mungkin untuk menggunakan penyeleksi jQuery / manipulasi DOM di sisi server menggunakan Node.js?

John
sumber
3
Saya bertanya-tanya: Mengapa menggunakan di sisi server sementara Anda bisa melakukannya di sisi klien?
Inanc Gumus
31
Mungkin Anda mungkin ingin membuat scraper web yang memo informasi spesifik secara berkala dan menyimpan hasilnya dalam database? Ini tidak akan sepraktis dari sisi klien.
Trevor
2
Anda juga harus melihat phantomjs, yang memungkinkan Anda untuk meniru sisi server browser dengan mesin V8.
Dimitri Kopriwa
2
Manipulasi @deeperx DOM di sisi server dapat berguna saat membuat perayap. Lihat jawaban ini .
Lucio Paiva
YA - lihat jawaban ini - Saya lebih suka ini daripada menggunakan cheerio, karena Anda mendapatkan kekuatan penuh pemilih jQuery.
monika mevenkamp

Jawaban:

563

Pembaruan (27-Juni-18) : Sepertinya ada pembaruan besar jsdomyang menyebabkan jawaban asli tidak lagi berfungsi. Saya menemukan jawaban ini yang menjelaskan cara menggunakan jsdomsekarang. Saya telah menyalin kode yang relevan di bawah ini.

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

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

Catatan: Jawaban awal gagal menyebutkan bahwa Anda perlu menginstal jsdom juganpm install jsdom

Pembaruan (akhir 2013) : Tim jQuery resmi akhirnya mengambil alih pengelolaan jquerypaket pada npm:

npm install jquery

Kemudian:

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

Philippe Rathé
sumber
43
Apakah mungkin menggunakan jQuery ajax dari node.js dengan modul npm itu?
ajsie
22
Tidak menginstal pada Windows (tanpa pekerjaan yang signifikan ), dalam hal ini saya akan merekomendasikan modul Cheerio: matthewmueller.github.com/cheerio
Simon East
7
+1 untuk menunjukkan di mana mendapatkan npm :) kebanyakan orang memiliki kebiasaan buruk hanya menyebutkan hal-hal seolah-olah itu harus diberikan (akal sehat)
Val
12
Ini kembali require("...").env is not a function.
Banderi
4
@ Banderi sama dengan saya, tahu? kesalahan:TypeError: require(...).env is not a function
coderInrRain
58

Ya Anda bisa, menggunakan perpustakaan yang saya buat bernama 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
sumber
20
Perhatikan bahwa nodeQuery sebenarnya mengubah halaman pengguna secara real time, jadi bahkan lebih keren dari yang diharapkan.
alessioalex
Saya sedang mencari sesuatu seperti ini ketika saya tersandung di sini ... Saya baru saja melihat paket nQuery dan jquery node dan nQuery telah diperbarui setahun yang lalu di mana jquery kemarin ... Apakah nQuery tidak lagi dikembangkan? dan apakah jquery mempengaruhi sisi klien seperti halnya nQuery? Adakah yang pernah mencoba keduanya?
Logan
2
@Logan nQuery pada dasarnya hanya jquery. perbedaannya adalah kode dijalankan di server dan, alih-alih mengirimkan kode jquery ke browser, ia menjalankan kode di server dan menjalankan manipulasi dom secara jarak jauh ke browser yang terhubung. Perhatikan juga bahwa nQuery adalah proyek percobaan, dan walaupun saya akan menerima permintaan tarikan untuk memperbaiki bug, itu tidak pernah dibuat untuk tujuan atau proyek tertentu sehingga tidak memiliki banyak komitmen
Thomas Blobaum
@ThomasBlobaum tidak bekerja untuk saya, kesalahan: , express = Express.createServer();dan TypeError: Express.createServer is not a functionada ide?
coderInrRain
@ThomasBlobaum sepertinya Anda belum mendapatkan versi Express terbaru. Coba npm install --save expressdi command prompt Anda.
gilbert-v
55

Pada saat penulisan juga ada Cheerio yang dipelihara .

Implementasi inti jQuery cepat, fleksibel, dan ramping yang dirancang khusus untuk server.

Alfred
sumber
2
+1 untuk Cheerio. jsdom, di sisi lain, sangat menyakitkan untuk dijalankan di Windows.
Simon East
1
Bisakah Cheerio menggunakan acara yang ditangguhkan dan panggilan ajax?
Hoffmann
6
tidak mendukung banyak penyeleksi seperti:gt(1)
chovy
1
Dalam pengalaman saya, yang ini paling berhasil. Jauh lebih cepat dari JSDOM.
Jason Prawn
1
@Offoff, saya menghabiskan satu detik untuk memeriksa dokumen untuk Anda. Tidak. Cheerio hanya memiliki metode terkait DOM.
Denis
39

Menggunakan jsdom sekarang Anda bisa. Lihat saja contoh jquery mereka di direktori contoh.

Benjamin Coe
sumber
satu sisi dari jsdom's jQueryify () adalah ia menjalankan semua skrip halaman.
drewish
dan itu tidak bekerja pada Windows tanpa banyak sakit kepala
Jason Goemaat
1
di 2016 Anda tidak perlu jsdom lagi - lihat jawaban saya: stackoverflow.com/a/40656811/3391783
low_rents
34

Perayap sederhana menggunakan Cheerio

Ini adalah rumus saya untuk membuat perayap sederhana di Node.js. Ini adalah alasan utama untuk ingin melakukan manipulasi DOM di sisi server dan mungkin itulah alasan mengapa Anda sampai di sini.

Pertama, gunakan requestuntuk mengunduh halaman yang akan diuraikan. Saat unduhan selesai, tangani untukcheerio dan mulai manipulasi DOM seperti menggunakan jQuery.

Contoh kerja:

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

Contoh ini akan mencetak ke konsol semua pertanyaan teratas yang ditampilkan di halaman beranda SO. Inilah sebabnya saya suka Node.js dan komunitasnya. Tidak bisa lebih mudah dari itu :-)

Instal dependensi:

npm instal permintaan cheerio

Dan jalankan (dengan asumsi skrip di atas ada dalam file crawler.js):

node crawler.js


Pengkodean

Beberapa halaman akan memiliki konten non-Inggris dalam penyandian tertentu dan Anda harus mendekodekannya UTF-8. Misalnya, halaman dalam bahasa Portugis Brasil (atau bahasa latin lainnya) kemungkinan akan dikodekan dalam ISO-8859-1(alias "latin1"). Ketika decoding diperlukan, saya katakan requestuntuk tidak menafsirkan konten dengan cara apa pun dan alih-alih menggunakannyaiconv-lite untuk melakukan pekerjaan itu.

Contoh kerja:

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

Sebelum berjalan, instal dependensi:

npm instal request iconv-lite cheerio

Dan akhirnya:

node crawler.js


Tautan berikut

Langkah selanjutnya adalah mengikuti tautan. Katakanlah Anda ingin mendaftar semua poster dari setiap pertanyaan teratas di SO. Anda harus terlebih dahulu mendaftar semua pertanyaan teratas (contoh di atas) dan kemudian memasukkan setiap tautan, mem-parsing setiap halaman pertanyaan untuk mendapatkan daftar pengguna yang terlibat.

Ketika Anda mulai mengikuti tautan, neraka panggilan balik dapat dimulai. Untuk menghindarinya, Anda harus menggunakan semacam janji, masa depan atau apa pun. Saya selalu menyimpan async di sabuk alat saya. Jadi, berikut adalah contoh lengkap perayap menggunakan 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);
            });
        });
    });
});

Sebelum berjalan:

npm instal request async cheerio

Jalankan tes:

node crawler.js

Output sampel:

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

Dan itulah dasar yang harus Anda ketahui untuk mulai membuat crawler Anda sendiri :-)


Perpustakaan digunakan

Lucio Paiva
sumber
22

di 2016 segalanya lebih mudah. instal jquery ke node.js dengan konsol Anda:

npm install jquery

ikat ke variabel $(misalnya - saya sudah terbiasa) dalam kode node.js Anda:

var $ = require("jquery");

lakukan hal-hal:

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

juga bekerja untuk tegukan karena didasarkan pada node.js.

low_rents
sumber
Versi node apa yang Anda gunakan? Di Mac, Node 6.10.2, jquery 2.2.4, var $ = require("jquery"); $.ajax // undefined (Diturunkan untuk saat ini).
AJP
@ AJP dan Anda yakin melakukannya npm install jqueryterlebih dahulu?
low_rents
1
Iya. > console.log(require("jquery").toString());memberi saya fungsi pabrik: function ( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); } Saya harus menggunakan jawaban di atas dengan jsdom: stackoverflow.com/a/4129032/539490
AJP
@ AJP ok, itu aneh.
low_rents
Saya mendapatkan fungsi pabrik yang persis sama dengan @AJP. Versi jquery apa yang Anda gunakan, @low_rents?
Boris Burkov
18

Saya yakin jawabannya sekarang ya.
https://github.com/tmpvar/jsdom

var navigator = { userAgent: "node-js" };  
var jQuery = require("./node-jquery").jQueryInit(window, navigator);
rdzah
sumber
9
Maaf melaporkan bahwa ini akan membutuhkan lebih banyak pekerjaan untuk menjalankan jQuery di jsdom Namun Sizzle bekerja! Saya benar-benar ingin menjaga jsdom seringan mungkin, jadi menambahkan emulasi browser lengkap seperti env.js sebenarnya bukan prioritas saat ini.
tmpvar
Sudahlah, saya menemukan salinan modifikasi yang dibundel dengan jsdom.
drewish
FYI simpul-jquery sudah tidak digunakan lagi karena jquery
Ruslan López
1
ReferenceError: window tidak didefinisikan
Bonn
17

npm install jquery --save #catat SEMUA RENDAH KASUS

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);
});
Nuh
sumber
ini jawaban yang rapi!
tolong jawab
8

Modul jQuery dapat diinstal menggunakan:

npm install jquery

Contoh:

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

Referensi jQuery di Node.js **:

SUNDARRAJAN K
sumber
2
Tidak berfungsi untuk saya ... C: \ ... \\ node_modules \ jquery \ dist \ jquery.js: 31 throw new Error ("jQuery membutuhkan jendela dengan dokumen"); ^ Kesalahan: jQuery memerlukan jendela dengan dokumen di module.exports (C: \ ... \ WebContent \ resources \ js \ node_modules \ jquery \ dist \ jquery.js: 31: 12)
Jose Manuel Gomez Alvarez
var jsdom = membutuhkan ("jsdom"); var window = jsdom.jsdom (). defaultView; jsdom.jQueryify (window, " code.jquery.com/jquery.js ", function () {var $ = window. $; $ ("body"). prepend ("<h1> Judul </h1>") ; console.log ($ ("h1"). html ());});
SUNDARRAJAN K
7

Anda harus mendapatkan jendela menggunakan API JSDOM baru.

const jsdom = require("jsdom");
const { window } = new jsdom.JSDOM(`...`);
var $ = require("jquery")(window);
Pekerjaan yang belum dipetakan
sumber
.JSDOM ( ...) harus .JSDOM ("<! DOCTYPE html>") untuk dukungan HTML5?
datdinhquoc
2

PERINGATAN

Solusi ini, seperti yang disebutkan oleh Golo Roden tidak benar . Ini hanya perbaikan cepat untuk membantu orang agar kode jQuery mereka yang sebenarnya berjalan menggunakan struktur aplikasi Node, tetapi itu bukan filosofi Node karena jQuery masih berjalan di sisi klien alih-alih di sisi server. Saya minta maaf karena memberikan jawaban yang salah.


Anda juga dapat membuat Jade dengan simpul dan memasukkan kode jQuery Anda di dalamnya. Ini adalah kode dari 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();
      });
Timbergus
sumber
4
Turun karena pertanyaan secara eksplisit menyatakan bahwa ini tentang jQuery di sisi server. Dengan hanya menyematkan jQuery ke file jade, jQuery masih berjalan di sisi klien. Karenanya, jawaban ini tidak membantu: - /
Golo Roden
2
OK, terima kasih banyak. Saya sudah memahaminya. Saya akan mencoba memperjelasnya dalam jawaban agar tidak membingungkan orang yang membacanya. Sekali lagi terima kasih atas bantuan Anda Golo.
Timbergus
2
Sama-sama :-). Dan tidak apa-apa: Kita semua membuat kesalahan, jadi jangan khawatir :-)
Golo Roden
2

Kode kerja saya adalah:

npm install jquery

lalu:

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

atau jika jendela ada, maka:

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

Modul jsdom adalah alat yang hebat. Tetapi jika Anda ingin mengevaluasi seluruh halaman dan melakukan beberapa hal funky di sisi server saya sarankan menjalankannya dalam konteks mereka sendiri:

vm.runInContext

Jadi hal-hal seperti require/ CommonJSdi situs tidak akan meledakkan proses Node Anda sendiri.

Anda dapat menemukan dokumentasi di sini . Bersulang!

Jakub Oboza
sumber
1

Pada jsdom v10, fungsi .env () sudah tidak digunakan lagi. Saya melakukannya seperti di bawah ini setelah mencoba banyak hal yang memerlukan 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);

Semoga ini bisa membantu Anda atau siapa saja yang pernah menghadapi masalah seperti ini.

Plabon Dutta
sumber
TypeError: JSDOM is not a constructor
Nathan Hawks
Jika Anda menjalankan jQuery di sisi Node, pertama, instal jquery dan jsdom menggunakan npm install. Kemudian, tambahkan baris di atas dalam file yang Anda coba gunakan pemilih jquery. Misalnya, saya menggunakan a $.each. Saya baru saja memasukkan baris-baris ini dan kemudian melakukannya seperti di bawah ini: $.each(errors, function (ind,error) { res.send(error.msg);console.log(error.msg); }); Semoga ini bisa membantu !!
Plabon Dutta
Entah bagaimana jsdom telah memutuskan untuk tidak menginstal sama sekali. Saya kira saya masih mencari tahu npm keluar. Terima kasih @
Nathan Hawks
0

Tidak satu pun dari solusi ini yang membantu saya dalam Aplikasi Elektron saya.

Solusi saya (solusi):

npm install jquery

Dalam index.jsfile Anda :

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

Dalam .jsfile Anda, tuliskan fungsi jQuery Anda dengan cara ini:

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

Tidak. Ini akan menjadi upaya yang cukup besar untuk port lingkungan browser ke node.

Pendekatan lain, yang saya sedang selidiki untuk pengujian unit, adalah membuat versi "Mock" dari jQuery yang menyediakan panggilan balik setiap kali seorang pemilih dipanggil.

Dengan cara ini Anda dapat menguji unit plugin jQuery Anda tanpa benar-benar memiliki DOM. Anda masih harus menguji di peramban nyata untuk melihat apakah kode Anda berfungsi di alam bebas, tetapi jika Anda menemukan masalah khusus peramban, Anda dapat dengan mudah "mengejek" yang ada di unit test Anda juga.

Saya akan mendorong sesuatu ke github.com/felixge setelah siap untuk ditampilkan.

Felix Geisendörfer
sumber
Saya suka ide ini ... itu seharusnya cukup mudah dilakukan.
Sudhir Jonathan
-1

Anda dapat menggunakan Electron , ini memungkinkan browser hybrid dan node.

Sebelumnya, saya mencoba menggunakan canvas2d di nodejs, tetapi akhirnya saya menyerah. Ini tidak didukung oleh nodejs default, dan terlalu sulit untuk menginstalnya (banyak banyak ... dependeces). Sampai saya menggunakan Electron, saya dapat dengan mudah menggunakan semua kode browserjs saya sebelumnya, bahkan WebGL, dan meneruskan nilai hasil (mis. Data base64 hasil gambar) ke kode nodejs.

akanvis
sumber
-9

Tidak yang saya tahu. DOM adalah hal sisi klien (jQuery tidak mem-parsing HTML, tetapi DOM).

Berikut adalah beberapa proyek Node.js saat ini:

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

Dan djangode SimonW sangat keren ...

Nosredna
sumber
Saya berharap itu mungkin. Saya sudah mencoba memasukkan jquery pada proyek node.js dan tentu saja itu tidak berhasil. jQuery didasarkan pada dokumen / jendela. Rhino mampu menjalankan sisi server jQuery: ejohn.org/blog/bringing-the-browser-to-the-server Saya akan mencari lebih banyak parser. Mungkin ada satu yang tidak bergantung pada browser.
John
@ John: satu-satunya alasan jQuery dapat berjalan di Badak adalah karena proyek ini: github.com/jeresig/env-js/blob/master/src/env.js Ini mensimulasikan sebagian kecil DOM dan runtime JavaScript. Ini bergantung pada Java apis sehingga tidak boleh digunakan untuk Node.js (yang menggunakan V8 / C ++).
Crescent Fresh
2
@Nosredna Meskipun ini mungkin benar ketika Anda menulisnya, itu jelas tidak benar lagi. Saya sarankan Anda menghapus jawaban Anda sekarang.
Keith Pinson
-18

Alternatifnya adalah menggunakan Underscore.js . Itu harus memberikan apa yang Anda inginkan dari sisi server dari JQuery.

John Wright
sumber
10
Bisakah Anda jelaskan? jQuery menyediakan banyak API manipulasi / traversing / filtering DOM. Garis bawah sepertinya utilitas perpustakaan umum yang tidak ada hubungannya dengan DOM.
Peter Lyons
1
Sama di sini, saya tidak melihat bagaimana ini relevan keduanya adalah pelengkap, bukan alternatif
Yi Jiang
2
Jawaban ini tidak sepenuhnya salah. jQuery dan Underscore melakukan overlap: keduanya menyediakan fitur seperti forEach.
tuomassalo
8
-1 Mereka memiliki fungsionalitas yang tumpang tindih tetapi Underscore bukan pengganti jQuery.
Sam
2
Pertanyaannya adalah bertanya tentang manipulasi / penyeleksi DOM.
mikermcneil