为什么' base'标签阻止jsdom.env工作?

时间:2013-05-28 06:27:43

标签: node.js web-scraping jsdom

更新

我在页面中找到了一个标签'base',我无法运行jQuery。如果网站包含该标签,jsdom就无法运行。虽然我不知道为什么。

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

为了验证这一点,我创建了一个全新的HTML文件并放入内部,然后jsdom失败。


我目前正在玩Node.js,在阅读How to Scrape Web Pages with Node.js and jQuery之后,我决定为我创建一个。

所以我安装了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树。即使我将$更改为其他名称,它仍然无效。

有人对此有所了解吗?

1 个答案:

答案 0 :(得分:2)

我看到这里发生了什么。这不是一个错误,但我可以看到它出乎意料的地方。这是正在发生的事情:

scripts: ['jquery.js']转换为“插入<script src="jquery.js">”。当jsdom看到<script src="jquery.js">时,它会尝试相对于当前文档的网址加载jquery.js

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

但是在带有<base>标记的文档中,文档的URL设置为该基础。因此,在这种情况下,<script src="jquery.js">会转换为加载<base href="http://localhost/jquery.js">,我敢打赌,在localhost端口80上运行的服务器上没有jquery.js。所以这会失败。

修复是更明确的。我建议像

这样的东西
var path = require("path");

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

请注意,如果您检查了errors变量,则可能会看到一个错误,为您提供线索。您似乎没有任何此类错误处理代码。