2013-05-28 6 views
1

Mise à jour:Pourquoi la balise 'base' empêche jsdom.env de fonctionner?

J'ai trouvé utilisé la « base » de la balise dans la page que je jQuery pas à exécuter dans Si le site contient cette balise le jsdom ne fonctionnerait pas.. Bien que je ne sais pas pourquoi.

<base href="http://bbs.18183.com/" /> 

Pour vérifier cela, je crée un fichier HTML flambant neuf et de mettre un à l'intérieur, l'jsdom échoue.


Je suis actuellement jouer avec Node.js, et après avoir lu How to Scrape Web Pages with Node.js and jQuery je décide de créer un pour moi. J'ai donc installé express, jsdom et beaucoup de choses et j'ai trouvé qu'il était très pratique de gratter les pages Web. Mais plus tard, je trouvais une étrange situation que certains page particulière ne peut être gratté, au lieu, il demande une erreur comme suit:

  var title = $('title').text(); 
        ^
TypeError: undefined is not a function 
    at H:\animalwar\personal\node\getter\app.js:82:23 
    at exports.env.exports.jsdom.env.scriptComplete (H:\animalwar\personal\node\ 
getter\node_modules\jsdom\lib\jsdom.js:207:39) 
    at process.startup.processNextTick.process._tickCallback (node.js:244:9) 

Voici mon code:

request({ 
    url:'http://bbs.18183.com/'}, 
    function (err, response, body) { 
    if(err && response.statusCode !== 200){ 
     console.log('Connection Failure! Fuck GFW'); 
     res.end('Connection Failure! Fuck GFW'); 
     return; 
    } 
    jsdom.env({ 
     html: body, 
     scripts: ['jquery.js'] 
     }, function(err, window){ 
     //Use jQuery just as in a regular HTML page 
     var $ = window.jQuery; 
     var title = $('title').text(); 
     console.log('SUCCESSFULLY GOT: ', title); 
     res.end(title); 
     } 
    ); 
}); 

Le site « http://bbs.18183.com/ » ne fonctionne pas dans ce cas, mais de nombreux autres sites fonctionnent. Par exemple, l'a changé pour "http://www.18183.com/", cela fonctionne.

Je suppose que c'est dû à un conflit de la définition de "$" mais plus tard, j'ai réalisé qu'avec jsdom.env la page est juste un arbre DOM. Même si j'ai changé $ à d'autres noms cela ne fonctionne toujours pas.

Est-ce que quelqu'un sait quelque chose à ce sujet?

Répondre

2

Je vois ce qui se passe ici. Ce n'est pas tout à fait un bug, mais je peux voir où c'est inattendu. Voici ce qui se passe:

scripts: ['jquery.js'] se traduit par "insérer un <script src="jquery.js">". Lorsque jsdom voit <script src="jquery.js">, il essaie de charger jquery.js par rapport à l'URL du document en cours.

Dans les documents sans balise <base>, lorsque vous les chargez explicitement avec des chaînes de fragment HTML plutôt que via des URL, l'URL du document est définie sur l'URL file:// correspondant à votre script actuel. Et je parie jquery.js est juste à côté de votre script actuel, donc cela fonctionne très bien: <script src="jquery.js"> résout très bien.

Mais dans les documents avec une balise <base>, l'URL du document est définie sur cette base. Donc, <script src="jquery.js"> dans ce cas se traduit par le chargement <base href="http://localhost/jquery.js">, et je parie que vous n'avez pas un jquery.js disponible sur un serveur fonctionnant sur le port local 80. Donc, cela échoue.

La correction doit être plus explicite. Je vous suggère quelque chose comme

var path = require("path"); 

jsdom.env({ 
    html: myHTML, 
    scripts: [path.resolve(__dirname, "jquery.js")], 
    done: function (errors, window) { 
    } 
}); 

Notez que si vous avez coché votre variable errors, vous auriez probablement vu une erreur qui vous a donné un indice. Vous ne semblez pas avoir un tel code de gestion des erreurs.

Questions connexes