我可以在 Node.js 中使用 jQuery 吗?

Is it possible to use jQuery selectors/DOM manipulation on the server-side using Node.js?

转载于:https://stackoverflow.com/questions/1801160/can-i-use-jquery-with-node-js

csdnceshi73
喵-见缝插针 DOM manipulation on the server side could be useful when making a crawler. See this answer.
5 年多之前 回复
csdnceshi52
妄徒之命 You should also take a look at phantomjs, which allow you to emulate a browser server side with V8 engine.
接近 6 年之前 回复
weixin_41568110
七度&光 Perhaps you might want to create a web scrapper that scraps specific information at regular intervals and stores the results in a database? This would not be as practical from the client-side.
6 年多之前 回复
weixin_41568127
?yb? I wonder: Why use on the server-side while you can do it on the client-side?
6 年多之前 回复

18个回答

Update (27-Jun-18): It looks like there was a major update to jsdom that causes the original answer to no longer work. I found this answer that explains how to use jsdom now. I've copied the relevant code below.

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

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

Note: The original answer fails to mention that it you will need to install jsdom as well using npm install jsdom

Update (late 2013): The official jQuery team finally took over the management of the jquery package on npm:

npm install jquery

Then:

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

csdnceshi55
~Onlooker now u can use let dom = new (require('jsdom').JSDOM)(htmlString); let $ = require('jquery')(dom.window);
2 年多之前 回复
weixin_41568208
北城已荒凉 JSDom updated their API with breaking changes but you can still use their old API with this... require('jsdom/lib/old-api').env( I got this from here: github.com/rstacruz/mocha-jsdom/issues/…
接近 3 年之前 回复
csdnceshi68
local-host Could you please update the version with which it shall work? Gives errors with latest versions
大约 3 年之前 回复
weixin_41568134
MAO-EYE same with me, any idea ? the error : TypeError: require(...).env is not a function
大约 3 年之前 回复
csdnceshi59
ℙℕℤℝ This code produces multiple "Warning: ... Critical dependency: the request of a dependency is an expression" :-(
3 年多之前 回复
csdnceshi76
斗士狗 This returns require("...").env is not a function.
3 年多之前 回复
csdnceshi66
必承其重 | 欲带皇冠 in 2016 it's way easier, see my answer: stackoverflow.com/a/40656811/3391783
接近 4 年之前 回复
csdnceshi56
lrony* phresnel: agreed. It sounds like @PaulVerest is screaming at the messenger. Further that was almost 3 years ago so whatever issues there were on Windows that he is 'bringing attention to' and discouraging others about may no longer even be relevant.
接近 5 年之前 回复
weixin_41568126
乱世@小熊 What's the point of your uppercases?
5 年多之前 回复
csdnceshi69
YaoRaoLov Yes, it is possible. See the instructions in this answer
大约 6 年之前 回复
weixin_41568110
七度&光 Referring to this link, what is the need to have that module if it does not work on server for dom traversal ?
6 年多之前 回复
csdnceshi74
7*4 I was able to build contextify just fine using Windows as of today. This may work just fine for windows users now.
接近 7 年之前 回复
weixin_41568184
叼花硬汉 Node JQuery (coolaj86/node-jquery) DOES NOT WORK ON WINDOWS
7 年多之前 回复
csdnceshi73
喵-见缝插针 +1 for showing where to get npm :) most people have a bad habit of just mentioning stuff as if it should be a given (common sense)
7 年多之前 回复
csdnceshi53
Lotus@ Doesn't install on Windows (without significant work), in which case I would recommend the Cheerio module: matthewmueller.github.com/cheerio
7 年多之前 回复
csdnceshi70
笑故挽风 Is it possible to use jQuery ajax from node.js with that npm module?
9 年多之前 回复

WARNING

This solution, as mentioned by Golo Roden is not correct. It is just a quick fix to help people to have their actual jQuery code running using a Node app structure, but it's not Node philosophy because the jQuery is still running on the client side instead of on the server side. I'm sorry for giving a wrong answer.


You can also render Jade with node and put your jQuery code inside. Here is the code of the jade file:

!!! 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();
      });
csdnceshi70
笑故挽风 You're welcome :-). And never mind: We all make our mistakes, so don't worry :-)
7 年多之前 回复
csdnceshi75
衫裤跑路 OK, thank you very much. I have understand it. I will try to clarify it in the answer in order to not confuse the people that read it. Thanks again for your help Golo.
7 年多之前 回复
csdnceshi70
笑故挽风 Downvoted because the question explicitly stated that it's about jQuery on the server-side. By simply embedding jQuery into a jade file jQuery is still run on the client-side. Hence, this answer does not help :-/
7 年多之前 回复

As of jsdom v10, .env() function is deprecated. I did it like below after trying a lot of things to require 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);

Hope this helps you or anyone who has been facing these types of issues.

</div>

A simple crawler using Cheerio

This is my formula to make a simple crawler in Node.js. It is the main reason for wanting to do DOM manipulation on the server side and probably it's the reason why you got here.

First, use request to download the page to be parsed. When the download is complete, handle it to cheerio and begin DOM manipulation just like using jQuery.

Working example:

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

This example will print to the console all top questions showing on SO home page. This is why I love Node.js and its community. It couldn't get easier than that :-)

Install dependencies:

npm install request cheerio

And run (assuming the script above is in file crawler.js):

node crawler.js


Encoding

Some pages will have non-english content in a certain encoding and you will need to decode it to UTF-8. For instance, a page in brazilian portuguese (or any other language of latin origin) will likely be encoded in ISO-8859-1 (a.k.a. "latin1"). When decoding is needed, I tell request not to interpret the content in any way and instead use iconv-lite to do the job.

Working example:

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

Before running, install dependencies:

npm install request iconv-lite cheerio

And then finally:

node crawler.js


Following links

The next step would be to follow links. Say you want to list all posters from each top question on SO. You have to first list all top questions (example above) and then enter each link, parsing each question's page to get the list of involved users.

When you start following links, a callback hell can begin. To avoid that, you should use some kind of promises, futures or whatever. I always keep async in my toolbelt. So, here is a full example of a crawler using 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);
            });
        });
    });
});

Before running:

npm install request async cheerio

Run a test:

node crawler.js

Sample output:

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

And that's the basic you should know to start making your own crawlers :-)


Libraries used

jQuery module can be installed using:

npm install jquery

Example:

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

References of jQuery in Node.js** :

csdnceshi54
hurriedly% 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()); });
大约 4 年之前 回复
csdnceshi70
笑故挽风 Doesn't work for me... C:\...\\node_modules\jquery\dist\jquery.js:31 throw new Error( "jQuery requires a window with a document" ); ^ Error: jQuery requires a window with a document at module.exports (C:\...\WebContent\resources\js\node_modules\jquery\dist\jquery.js:31:12)
大约 4 年之前 回复

The module jsdom is a great tool. But if you want to evaluate entire pages and do some funky stuff on them server side I suggest running them in their own context:

vm.runInContext

So things like require / CommonJS on site will not blow your Node process itself.

You can find documentation here. Cheers!

My working code is:

npm install jquery

and then:

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

or if the window is present, then:

typeof window !== "undefined" ? window : this;
window.jQuery   = require('jquery');
window.$        = window.jQuery;
csdnceshi51
旧行李 works on electron ^2.0.0 :)
2 年多之前 回复

Yes you can, using a library I created called nodeQuery https://github.com/tblobaum/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);
csdnceshi75
衫裤跑路 not working for me, error : , express = Express.createServer(); and TypeError: Express.createServer is not a function any idea ?
大约 3 年之前 回复
csdnceshi71
Memor.の This throws i.imgur.com/7Hf5dxd.png
6 年多之前 回复
csdnceshi65
larry*wei nQuery is basically just jquery. the difference is the code is run on the server and, rather than delivering the jquery code to the browser, it runs the code on the server and remotely executes dom manipulation to connected browsers. Also note that nQuery was an experimental project, and while I will accept pull requests to fix bugs, it was never created for any specific purpose or project so it has not had many commits
接近 8 年之前 回复
csdnceshi50
三生石@ I was searching something like this when I stumbled here... I have just looked at nQuery and jquery node packages and nQuery was updated a year ago where jquery was yesterday... Is nQuery no longer developed? and does jquery affect client side as nQuery does? Has anybody tried them both maybe?
接近 8 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 Note that nodeQuery is actually changing the page of the user in real time, so it's even cooler than one might expect.
接近 9 年之前 回复

At the time of writing there also is the maintained Cheerio.

Fast, flexible, and lean implementation of core jQuery designed specifically for the server.

csdnceshi51
旧行李 I spent a second to check docs for you. No, it does not. Cheerio has DOM-related methods only.
接近 5 年之前 回复
csdnceshi76
斗士狗 In my experience this one works best. Its a lot faster than JSDOM.
大约 6 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 does not support a lot of selectors like :gt(1)
6 年多之前 回复
csdnceshi54
hurriedly% Can Cheerio use deferred events and ajax calls?
6 年多之前 回复
weixin_41568208
北城已荒凉 +1 for Cheerio. jsdom, on the other hand, is really painful to get running on Windows.
7 年多之前 回复

I believe the answer to this is now yes.
https://github.com/tmpvar/jsdom

var navigator = { userAgent: "node-js" };  
var jQuery = require("./node-jquery").jQueryInit(window, navigator);
csdnceshi61
derek5. FYI node-jquery is deprecated now in favor of jquery
2 年多之前 回复
csdnceshi74
7*4 never mind, i found the modified copy that's bundled with jsdom.
8 年多之前 回复
csdnceshi74
7*4 could you say more about how to get sizzle to work?
8 年多之前 回复
csdnceshi50
三生石@ I'm sorry to report that it is going to take more work to get jQuery running on jsdom. Sizzle however does work! I really want to keep jsdom as light as possible, so adding in full browser emulation like env.js is not really a priority at this time.
10 年多之前 回复
共18条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐