1

更新:

我发现页面中使用了一个标签“base”,但未能在其中运行 jQuery。如果网站包含该标签,则 jsdom 将无法工作。虽然我不知道为什么。

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

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


我目前正在使用 Node.js,在阅读了如何使用 Node.js 和 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 树。即使我将 $ 更改为其他名称,它仍然不起作用。

有人对这个有了解吗?

4

1 回答 1

2

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

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

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

但是在带有<base>标签的文档中,文档的 URL 被设置为该基础。所以<script src="jquery.js">在这种情况下转换为 loading <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变量,您可能会看到一个错误提示。您似乎没有任何此类错误处理代码。

于 2013-06-03T07:01:16.503 回答