为什么“基地”标记是防止jsdom.env工作?

更新:

我发现页面中使用的标记“base”,我没有运行jQuery。如果网站包含该标记,jsdom将不起作用。 虽然我不知道为什么。

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

为了validation这一点,我创build了一个全新的HTML文件,并放入一个里面,jsdom然后失败。


我目前在玩Node.js,在阅读了如何使用Node.js和jQuery来抓取网页之后,我决定为我创build一个。

所以我安装了express,jsdom和很多东西,发现抓取网页真的很方便。 但后来我发现了一个奇怪的情况,某个特定的页面不能被抓取,而是提示错误如下:

  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) 

这是我的代码:

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

网站“ http://bbs.18183.com/ ”在这种情况下不起作用,但许多其他网站正在工作。 例如,将其更改为“ http://www.18183.com/ ”,正在工作。

我想这是由于“$”的定义冲突,但后来我意识到,与jsdom.env页面只是一个DOM树。 即使我改变了其他名字,它仍然无法正常工作。

有人对这个有了解吗?

我看到这里发生了什么。 这不是一个错误,但我可以看到它的意外。 这是发生了什么事情:

scripts: ['jquery.js']翻译成“插入<script src="jquery.js"> ”。 当jsdom看到<script src="jquery.js"> ,它会尝试加载相对于当前文档的URL的jquery.js

在没有<base>标签的文档中,当使用HTML片段string而不是通过URL显式地加载它们时,文档URL被设置为与当前脚本对应的file:// URL。 我敢打赌, jquery.js就在你的当前脚本的旁边,所以这很好用: <script src="jquery.js">解决就好了。

但在具有<base>标签的文档中,文档的URL被设置为该基础。 因此,在这种情况下, <script src="jquery.js">转换为加载<base href="http://localhost/jquery.js"> ,我打赌你没有在服务器上提供jquery.js在本地主机端口80上运行。所以这失败了。

修复是更加明确的。 我会build议类似的

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

请注意,如果你检查了你的errorsvariables,你可能会看到一个错误,给你一个线索。 你似乎没有任何这样的error handling代码。