Чи можу я використовувати jQuery з Node.js?


574

Чи можливо використовувати селектори jQuery / DOM на стороні сервера за допомогою Node.js?


3
Цікаво: навіщо використовувати на стороні сервера, коли ви можете це робити на стороні клієнта?
Інаксі Гюмус

31
Можливо, ви захочете створити веб-скребок, який регулярно записує конкретну інформацію та зберігає результати в базі даних? Це не буде настільки практично з боку клієнта.
Тревор

2
Ви також повинні поглянути на phantomjs, які дозволяють емулювати сторону сервера браузера за допомогою двигуна V8.
Димитрій Копріва

2
@deeperx DOM маніпулювання на стороні сервера може бути корисним при створенні сканера. Дивіться цю відповідь .
Lucio Paiva

ТАК - погляньте на цю відповідь - я віддаю перевагу цьому над використанням cheerio, оскільки ви отримуєте повну потужність селектора jQuery.
monika mevenkamp

Відповіді:


563

Оновлення (27 червня-18) : Схоже, відбулося велике оновлення, jsdomяке спричиняє, що оригінальна відповідь більше не працює. Я знайшов цю відповідь, яка пояснює, як jsdomзараз користуватися. Я скопіював відповідний код нижче.

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

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

Примітка: в оригінальній відповіді не зазначається, що для цього вам потрібно буде встановити jsdom, використовуючиnpm install jsdom

Оновлення (кінець 2013 р.) : Офіційна команда jQuery нарешті взяла на себе управління jqueryпакетом у npm:

npm install jquery

Тоді:

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


43
Чи можна використовувати jQuery ajax від node.js з цим модулем npm?
ajsie

22
Не встановлюється в Windows (без значних робіт), і тоді я рекомендував би модуль Cheerio: matthewmueller.github.com/cheerio
Simon East

7
+1, щоб показати, де взяти npm :) У більшості людей погана звичка згадувати речі, як ніби це має бути дано (здоровий глузд)
Val

12
Це повертається require("...").env is not a function.
Бандері

4
@Banderi те саме зі мною, будь-яка ідея? помилка:TypeError: require(...).env is not a function
coderInrRain

58

Так, ви можете, використовуючи створену мною бібліотеку під назвою 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
Зауважте, що nodeQuery насправді змінює сторінку користувача в режимі реального часу, тому це навіть крутіше, ніж можна було очікувати.
alessioalex

Я шукав щось подібне, коли натрапив сюди ... Я щойно переглянув пакунки вузлів nQuery та jquery, і nQuery було оновлено рік тому, де jquery був вчора ... Чи nQuery вже не розвинений? і чи впливає jquery на сторону клієнта, як це робить nQuery? Хтось може спробував їх обох, можливо?
Логан

2
@Logan nQuery - це лише jquery. Різниця полягає в тому, що код запускається на сервері, і замість того, щоб доставити код jquery до браузера, він запускає код на сервері і віддалено виконує маніпуляцію з домом для підключених браузерів. Також зауважте, що nQuery був експериментальним проектом, і хоча я буду приймати запити на виправлення помилок, він ніколи не створювався для будь-якої конкретної мети чи проекту, тому у нього не було багато
комітів

@ThomasBlobaum не працює для мене, помилка: , express = Express.createServer();і TypeError: Express.createServer is not a functionбудь-яка ідея?
coderInrRain

@ThomasBlobaum виглядає так, що у вас немає останньої версії Express. Спробуйте npm install --save expressу своєму командному рядку.
gilbert-v

55

На момент написання там також зберігається Cheerio .

Швидка, гнучка та швидка реалізація основних jQuery, розроблених спеціально для сервера.


2
+1 для Cheerio. З іншого боку, jsdom дуже боляче працювати на Windows.
Simon Simon

1
Чи може Cheerio використовувати відкладені події та ajax-дзвінки?
Гофман

6
не підтримує багато селекторів на кшталт:gt(1)
chovy

1
На мій досвід, це найкраще працює. Це набагато швидше, ніж JSDOM.
Джейсон Креун

1
@Hoffmann, я витратив секунду, щоб перевірити документи для тебе. Ні, це не є. Cheerio має лише методи, пов'язані з DOM.
Денис

39

Використовувати jsdom ви тепер можете. Просто подивіться їх приклад jquery в каталозі прикладів.


одна нижня сторона jQueryify () jsdom - це те, що вона виконує всі сценарії сторінки.
мандрівний

і він не працює в Windows без великих головних болів
Jason Goemaat

1
в 2016 році вам не потрібно jsdom більше - см моя відповідь: stackoverflow.com/a/40656811/3391783
low_rents

34

Простий гусеничний за допомогою Cheerio

Це моя формула зробити простий сканер у Node.js. Це головна причина того, що потрібно робити маніпуляції з DOM на стороні сервера, і, мабуть, це причина, чому ви потрапили сюди.

По-перше, використовуйте requestдля завантаження сторінки для розбору. Коли завантаження завершиться, зверніться до ньогоcheerio та розпочніть маніпуляцію з DOM так само, як за допомогою jQuery.

Робочий приклад:

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

Цей приклад надрукує на консоль усі найпопулярніші запитання, що відображаються на домашній сторінці SO. Ось чому я люблю Node.js та його спільноту. Це не могло бути легшим за це :-)

Встановити залежності:

npm встановити запит cheerio

І запустіть (якщо припустити, що сценарій знаходиться у файлі crawler.js):

вузол crawler.js


Кодування

Деякі сторінки матимуть вміст, що не має англійської мови, у певному кодуванні, і вам потрібно буде його розшифрувати UTF-8. Наприклад, сторінка бразильською португальською мовою (або будь-якою іншою мовою латинського походження), ймовірно, буде закодована в ISO-8859-1(також "latin1"). Коли потрібно декодування, я кажу requestне інтерпретувати вміст жодним чином, а замість цього використовуватиiconv-lite виконувати завдання.

Робочий приклад:

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

Перед запуском встановіть залежності:

npm встановити запит iconv-lite cheerio

І тоді нарешті:

вузол crawler.js


Наступні посилання

Наступним кроком буде перехід за посиланнями. Скажіть, що ви хочете перерахувати всі афіші з кожного головного запитання на ТАК. Спочатку потрібно перерахувати всі найпопулярніші запитання (приклад вище), а потім ввести кожне посилання, проаналізувавши сторінку кожного питання, щоб отримати список залучених користувачів.

Коли ви почнете переходити за посиланнями, може початися пекельний зворотний дзвінок . Щоб уникнути цього, вам слід використовувати якісь обіцянки, ф'ючерси чи що завгодно. Я завжди зберігаю асинхронізацію в моєму поясі інструментів. Отже, ось повний приклад сканера, що використовує 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);
            });
        });
    });
});

Перед запуском:

npm встановити запит async cheerio

Проведіть тест:

вузол crawler.js

Вибірка зразка:

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

І це основне, що ви повинні знати, щоб почати робити власні сканери :-)


Бібліотеки, що використовуються


22

у 2016 році все простіше. встановіть jquery на node.js за допомогою консолі:

npm install jquery

прив’яжіть його до змінної $(наприклад, я звик до неї) у вашому коді node.js:

var $ = require("jquery");

робити речі:

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

також працює для gulp, оскільки він заснований на node.js.


Яку версію вузла ви використовуєте? На Mac, Node 6.10.2, jquery 2.2.4, var $ = require("jquery"); $.ajax // undefined (На сьогоднішній день)
AJP

@AJP, і ви впевнені, що зробили npm install jqueryперше?
low_rents

1
Так. > console.log(require("jquery").toString());дає мені фабричну функцію: function ( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); } я повинен був використовувати відповідь вище з jsdom: stackoverflow.com/a/4129032/539490
AJP

@AJP добре, це дивно.
low_rents

Я отримую абсолютно таку ж заводську функцію, що і @AJP. Яку версію jquery ви використовували, @low_rents?
Борис Бурков

18

Я вважаю, що відповідь на це зараз - так.
https://github.com/tmpvar/jsdom

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

9
Пробачте, повідомляю, що для отримання jQuery на jsdom буде потрібно більше роботи. Sizzle проте працює! Мені дуже хочеться зберегти jsdom якомога легше, тому додавання в повній емуляції браузера, як env.js, наразі не є пріоритетним завданням.
tmpvar

Неважливо, я знайшов модифіковану копію, яка в комплекті з jsdom.
велетенський

FYI-вузол jquery зараз застарілий на користь jquery
Руслан Лопес,

1
ReferenceError: вікно не визначено
Бонн

17

npm install jquery --save #note ВСІ НЕЗАЛЕЖНОСТІ

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

це акуратна відповідь! pls підтверджуйте це
datdinhquoc

8

Модуль jQuery можна встановити за допомогою:

npm install jquery

Приклад:

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

Посилання jQuery в Node.js **:


2
Не працює для мене ... C: \ ... \\ node_modules \ jquery \ dist \ jquery.js: 31 кинути нову помилку ("jQuery вимагає вікно з документом"); ^ Помилка: jQuery вимагає вікна з документом у module.exports (C: \ ... \ WebContent \ ресурси \ js \ node_modules \ jquery \ dist \ jquery.js: 31: 12)
Жозе Мануель Гомес Альварес

var jsdom = requ ("jsdom"); var window = jsdom.jsdom (). defaultView; jsdom.jQueryify (вікно, " code.jquery.com/jquery.js ", функція () {var $ = window. $; $ ("body"). prepend ("<h1> Назва </h1>") ; console.log ($ ("h1"). html ());});
SUNDARRAJAN K

7

Ви повинні отримати вікно за допомогою нового API JSDOM.

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

.JSDOM ( ...) має бути .JSDOM ("<! DOCTYPE html>") для підтримки HTML5?
datdinhquoc

2

УВАГА

Це рішення, як згадував Голо Роден, є невірним . Це просто швидке виправлення, щоб допомогти людям мати власний код jQuery за допомогою структури додатків Node, але це не філософія Node, оскільки jQuery все ще працює на стороні клієнта, а не на стороні сервера. Вибачте за те, що ви дали неправильну відповідь.


Ви також можете відтворити Jade за допомогою вузла і помістити код jQuery всередину. Ось код файлу нефриту:

!!! 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
Зрозуміло, оскільки в питанні прямо сказано, що мова йде про jQuery на стороні сервера. Просто вставляючи jQuery у нефритовий файл, jQuery все ще виконується на стороні клієнта. Отже, ця відповідь не допомагає: - /
Голо Роден

2
Добре, дуже дякую. Я це зрозумів. Я спробую уточнити це у відповіді, щоб не заплутати людей, які її читають. Ще раз дякую за вашу допомогу Голо.
Тімберг

2
Ласкаво просимо :-). І неважливо: ми всі робимо свої помилки, тому не хвилюйтесь :-)
Голо Роден

2

Мій робочий код:

npm install jquery

і потім:

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

або якщо вікно присутнє, то:

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

1

Модуль jsdom - чудовий інструмент. Але якщо ви хочете оцінити цілі сторінки та зробити якісь прикольні речі на стороні сервера, я пропоную запустити їх у власному контексті:

vm.runInContext

Тож такі речі, як require/CommonJS на сайті, не підірвуть сам процес вашого вузла.

Ви можете знайти тут документацію . Ура!


1

Станом на jsdom v10 функція .env () застаріла. Я зробив це як нижче, спробувавши багато речей, щоб вимагати 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);

Сподіваємось, це допоможе вам або будь-кому, хто стикався з подібними проблемами.


TypeError: JSDOM is not a constructor
Натан Хокс

Якщо ви використовуєте jQuery на стороні Вузола, по-перше, встановіть jquery та jsdom, використовуючи npm install. Потім додайте вище рядки у файл, у якому ви намагаєтесь використовувати селектор jquery. Наприклад, я використав a $.each. Я щойно включив ці рядки, а потім зробив це як нижче: $.each(errors, function (ind,error) { res.send(error.msg);console.log(error.msg); }); Сподіваюся, це допомагає !!
Плабон Дутта

Якось jsdom вирішив взагалі не встановлювати. Я здогадуюсь, я все ще з'ясовую npm. Спасибі @
Натан Хокс


0

Жодне з цих рішень не допомогло мені в моєму додатку Electron.

Моє рішення (вирішення):

npm install jquery

У вашому index.jsфайлі:

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

У свої .jsфайли запишіть свої функції jQuery таким чином:

jQuery(document).ready(function() {

0

Так, jQueryможна використовувати з Node.js.

Кроки для включення jQuery в проект вузла: -

npm i jquery --save Включіть jquery в коди

import jQuery from 'jquery';

const $ = jQuery;

Я завжди використовую jquery в проектах node.js, зокрема в проекті розширення хрому.

наприклад https://github.com/fxnoob/gesture-control-chrome-extension/blob/master/src/default_plugins/tab.js


-1

Ні. Це буде досить велике зусилля, щоб перенести середовище браузера для вузла.

Інший підхід, який я зараз досліджую для тестування одиниць, полягає у створенні "Mock" версії jQuery, яка забезпечує зворотні виклики щоразу, коли викликається селектор.

Таким чином, ви можете перевірити свої плагіни jQuery, фактично не маючи DOM. Вам все одно доведеться протестувати в реальних браузерах, щоб побачити, чи працює ваш код у дикій природі, але якщо ви виявите проблеми, пов’язані з веб-переглядачем, ви також можете легко «знущатися над» з ваших тестових модулів.

Щойно я підкажу щось до github.com/felixge, коли воно буде готове до показу.


Мені подобається ця ідея ... зробити це слід досить просто.
Sudhir Jonathan

-1

Ви можете використовувати Electron , він дозволяє гібридні браузери та nodejs.

Раніше я намагався використовувати canvas2d в nodejs, але нарешті я відмовився. Він не підтримується nodejs за замовчуванням, і занадто важко його встановити (багато багатьох ... залежних). Поки я не використовую Electron, я можу легко використовувати весь свій попередній код браузера, навіть WebGL, і передати значення результату (наприклад, зображення зображень результатів base64) в код nodejs.


-9

Не те, що я знаю. DOM - це сторона, що стосується клієнта (jQuery розбирає не HTML, а DOM).

Ось кілька поточних проектів Node.js:

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

А джангкод SimonW досить чортово крутий ...


Я б хотів, щоб це було можливо. Я вже намагався включати jquery в проект node.js, і, звичайно, він не працював. jQuery заснований на документі / вікні. Rhino здатний запускати сторону сервера jQuery: ejohn.org/blog/bringing-the-browser-to-the-server Я буду шукати більше парсерів. Можливо, є такий, який не залежить від браузера.
Джон

@John: Єдина причина, що jQuery може працювати на Rhino, це через цей проект: github.com/jeresig/env-js/blob/master/src/env.js Він імітує невелику частину DOM та JavaScript під час виконання. Він покладається на Java apis, тому не використовується для Node.js (який використовує V8 / C ++).
Півмісяць Свіжий

2
@Nosredna Хоча це, можливо, було правдою, коли ви це писали, це явно вже не відповідає дійсності. Пропоную видалити відповідь зараз.
Кіт Пінсон

-18

Альтернативою є використання Underscore.js . Він повинен забезпечити те, що ви могли б хотіти на сервері від JQuery.


10
Ви можете пояснити? jQuery надає безліч API інтерфейсів для маніпулювання / проходження / фільтрації DOM. Підкреслення виглядає як загальні утиліти бібліотеки, що не мають нічого спільного з DOM.
Пітер Ліонс

1
Тут же я не бачу, наскільки це актуально, це два доповнення, а не альтернативи
Yi Jiang

2
Ця відповідь не зовсім помилкова. jQuery і Underscore перекриваються: вони забезпечують такі функції, як forEach.
tuomassalo

8
-1 Вони мають функціональні функції, що перекриваються, але підкреслення не є заміною jQuery.
Сем

2
Питання, проте, про DOM маніпуляції / селектори, хоча.
mikermcneil
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.