网站抓取使用zombie.js的问题

问题描述:

我需要做一些网络抓取。在使用不同的Web测试框架之后,其中大多数地方的速度太慢(Selenium)或者我的需求太多(env.js),我认为zombie.js看起来最有希望,因为它使用一组可靠的库进行HTML解析和DOM操作。然而,在我看来,像它竟然不支持基本的基于事件的Javascript代码如以下网页:网站抓取使用zombie.js的问题

<html> 
    <head> 
    <title>test</title> 
    <script type="text/javascript"> 

     console.log("test script executing..."); 
     console.log("registering callback for event DOMContentLoaded on " + document); 

     document.addEventListener('DOMContentLoaded', function(){ 
     console.log("DOMContentLoaded triggered"); 
     }, false); 

     function loaded() { 
     console.log("onload triggered"); 
     } 

    </script> 
    </head> 

    <body onload="loaded();"> 
    <h1>Test</h1> 
    </body> 
</html> 

我于是决定手动触发这些事件是这样的:

zombie = require("zombie"); 

zombie.visit("http://localhost:4567/", { debug: true }, function (err, browser, status) { 

    doc = browser.document; 
    console.log("firing DOMContentLoaded on " + doc); 
    browser.fire("DOMContentLoaded", doc, function (err, browser, status) { 

    body = browser.querySelector("body"); 
    console.log("firing load on " + body); 
    browser.fire("load", body, function (err, browser, status) { 

     console.log(browser.html()); 

    }); 
    }); 

}); 

这适用于这个特定的测试页面。不过,我的问题是更普遍的问题:我希望能够在Facebook上抓取更复杂的基于AJAX的网站(如http://www.facebook.com/profile.php?id=100000028174850&sk=friends&v=friends)。使用僵尸登录到网站并不是问题,但是像这些列表这样的内容似乎完全使用AJAX加载,我不知道如何触发启动加载的事件处理程序。

有几个问题我有一个关于这个问题:

  • 已有人已经实施了类似的复杂刮不使用浏览器进行远程控制一样硒的解决方案?
  • 是否有一些有关基于JavaScript的复杂页面加载过程的参考?
  • 有人可以提供关于如何调试真正的浏览器,看看我可能需要执行触发Facebook事件处理程序的建议吗?
  • 有关此主题的任何其他想法?

再次,请不要指出我涉及控制像Selenium这样的真正浏览器的解决方案,因为我知道这些。不过,欢迎提供一些真正的内存中渲染器的建议,如WebKit可以从Ruby脚本语言访问,但最好能够设置cookie,并且最好还可以加载原始HTML,而不是触发真正的HTTP请求。

+0

你正在寻找一个JavaScript测试框架或Web数据提取工具吗?如果你只是在寻找一个scree-scraping工具,那么可以在不执行Javascript的情况下刮掉大多数网站,甚至是AJAX重量级的网站。 – chesles

+1

问题是关于网络抓取。你是对的,通常确实有可能在不执行Js的情况下做到这一点,例如通过手动发布REST请求。在Facebook的情况下,只需使用HTTP和HTML解析就可以抓取该网站的移动版本。但我对通用解决方案感兴趣,它理解Javascript并且不需要真正的浏览器实例。这似乎是可能的,因为env.Js和zombie.Js显示,但它似乎是一个技巧问题。 –

为了进行数据提取,运行“无头浏览器”并手动触发javascript事件不会是最简单的事情。虽然不是不可能,但有更简单的方法来做到这一点。

大多数网站,即使是AJAX重量级的网站,都可以在不执行其单个Javascript代码的情况下被抓取。实际上,通常比试图找出一个网站的Javascript代码要容易得多,该代码经常被混淆,缩小并难以调试。如果你对HTTP有深刻的理解,你就会明白为什么:(几乎)与服务器的所有交互都被编码为HTTP请求,因此无论它们是由Javascript发起的,还是用户点击链接或bot程序中的自定义代码,这对服务器没有任何影响。 (我之所以这样说,几乎是因为当Flash或applets涉入时,不知道数据在哪里飞行;它们可以是特定于应用程序的,但Javascript中的任何操作都将通过HTTP进行。)

也就是说,在任何使用定制软件的网站上模仿用户。首先,您必须能够看到发送到服务器的原始HTTP请求。您可以使用代理服务器来记录真实浏览器向目标网站发出的请求。有许多工具可以用于此目的:CharlesFiddler非常方便,最专注screen-scraper tools有一个基本的代理内置,Firefox和Chrome的Firebug扩展具有类似的工具来查看AJAX请求...你会得到这个想法。

一旦您可以看到由于网站上的特定操作而产生的HTTP请求,很容易编写程序来模仿这些请求;只需将相同的请求发送到服务器,它就会像处理特定操作的浏览器一样对待您的程序。

不同的语言库提供不同的功能。对于红宝石来说,我看到很多人使用mechanize for ruby

如果数据提取是您唯一的目标,那么您几乎总能通过这种方式模仿HTTP请求来获得所需的内容。不需要Javascript。因为Facebook提供了检测自动访问的措施(它们使用的不仅仅是验证码),因为Facebook提供的Facebook特别困难(尽管不是不可能)非常困难(尽管不是不可能)。如果他们发现可疑活动,他们将会禁用该帐户。毕竟,这是对他们的terms of service(第3.2节)。

+1

谢谢你为这个问题提出复杂的答案。我已经使用Firebug和Fiddler2来监控HTTP和Web服务器之间的流量,但是如果使用难以反向的通信主题,这是非常有用的,正如很多社交网站所做的那样。但即使可以使用底层接口与Web服务器交互并提取信息,这也需要不断调整scraper,这可能非常耗时。 Env.js(我最喜欢的工作,因为我想)表明,它实际上可以通过编程模拟一个真正的浏览器。 –

+0

确实如此,Facebook和其他网站试图尽可能让你刮掉他们的网站;他们更喜欢你使用他们的API,这样他们可以更好地控制你的程序访问什么,并因此更好地保护他们的用户的隐私。 – chesles

+0

尽管如此,使用像Selenium这样的工具来模拟冲浪用户似乎没有任何问题(除了缓慢),除了大量使用动态内容之外,我没有遇到任何障碍。即使OAuth没有针对自动访问进行保护,认证可以没有任何问题地编写脚本,甚至不需要使用Javascript。 –