你如何抓取 AJAX 页面?

Posted

技术标签:

【中文标题】你如何抓取 AJAX 页面?【英文标题】:How do you scrape AJAX pages? 【发布时间】:2010-09-20 14:32:42 【问题描述】:

请告知如何抓取 AJAX 页面。

【问题讨论】:

【参考方案1】:

概述:

所有屏幕抓取首先需要手动检查您要从中提取资源的页面。在处理 AJAX 时,您通常只需要分析一些内容,而不仅仅是 html

在处理 AJAX 时,这仅意味着您想要的值不在您请求的初始 HTML 文档中,而是将执行 javascript 请求服务器提供您想要的额外信息。

因此,您通常可以简单地分析 javascript 并查看 javascript 发出的请求,然后从一开始就调用此 URL。


示例:

以此为例,假设你要抓取的页面有如下脚本:

<script type="text/javascript">
function ajaxFunction()

var xmlHttp;
try
  
  // Firefox, Opera 8.0+, Safari
  xmlHttp=new XMLHttpRequest();
  
catch (e)
  
  // Internet Explorer
  try
    
    xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
    
  catch (e)
    
    try
      
      xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
      
    catch (e)
      
      alert("Your browser does not support AJAX!");
      return false;
      
    
  
  xmlHttp.onreadystatechange=function()
    
    if(xmlHttp.readyState==4)
      
      document.myForm.time.value=xmlHttp.responseText;
      
    
  xmlHttp.open("GET","time.asp",true);
  xmlHttp.send(null);
  
</script>

那么您需要做的就是向同一服务器的 time.asp 发出 HTTP 请求。 Example from w3schools.


使用 C++ 进行高级抓取:

对于复杂的用法,如果您使用 C++,您还可以考虑使用 firefox javascript 引擎SpiderMonkey 在页面上执行 javascript。

使用 Java 进行高级抓取:

对于复杂的用法,如果您使用 Java,您还可以考虑使用适用于 Java 的 firefox javascript 引擎Rhino

使用 .NET 进行高级抓取:

对于复杂的使用,如果您使用的是 .Net,您还可以考虑使用 Microsoft.vsa 程序集。最近替换为 ICodeCompiler/CodeDOM。

【讨论】:

哇,即使现在有了像 phantomjs 这样的工具,这也是非常有用的信息,一旦您调查了幕后发生的事情,知道如何使用所述方法自定义抓取页面会更加方便谢谢很多布莱恩+1【参考方案2】:

在我看来,最简单的解决方案是使用Casperjs,这是一个基于 WebKit 无头浏览器 phantomjs 的框架。

整个页面加载完毕,很容易抓取任何与 ajax 相关的数据。 你可以查看这个基础教程来学习Automating & Scraping with PhantomJS and CasperJS

您还可以查看此示例代码,了解如何抓取 google 建议的关键字:

/*global casper:true*/
var casper = require('casper').create();
var suggestions = [];
var word = casper.cli.get(0);

if (!word) 
    casper.echo('please provide a word').exit(1);


casper.start('http://www.google.com/', function() 
    this.sendKeys('input[name=q]', word);
);

casper.waitFor(function() 
  return this.fetchText('.gsq_a table span').indexOf(word) === 0
, function() 
  suggestions = this.evaluate(function() 
      var nodes = document.querySelectorAll('.gsq_a table span');
      return [].map.call(nodes, function(node)
          return node.textContent;
      );
  );
);

casper.run(function() 
  this.echo(suggestions.join('\n')).exit();
);

【讨论】:

但是如何与 php 一起使用呢? 您使用 shell_exec 启动它。别无选择。【参考方案3】:

如果可以,请尝试检查 DOM 树。 Selenium 将其作为测试页面的一部分。它还具有单击按钮和跟踪链接的功能,这可能很有用。

【讨论】:

在 selenium 客户端脚本中,您可以使用 get_html_source() 函数,但它返回正常源,而不是生成的(AJAX 后)源。如果您知道如何访问生成的源代码,请告诉我们。【参考方案4】:

使用 Ajax 或一般使用 Javascript 抓取网页的最佳方法是使用浏览器本身或无头浏览器(没有 GUI 的浏览器)。目前phantomjs 是一款使用WebKit 推广的无头浏览器。我成功使用的替代方法是HtmlUnit(在Java 或.NET 中通过IKVM,这是一个模拟浏览器。另一个已知的替代方法是使用像Selenium 这样的网络自动化工具。

我写了很多关于这个主题的文章,比如web scraping Ajax and Javascript sites 和automated browserless OAuth authentication for Twitter。在第一篇文章的末尾,有很多我从 2011 年以来一直在编译的额外资源。

【讨论】:

【参考方案5】:

我喜欢PhearJS,但这可能部分是因为我构建了它。

也就是说,它是您在后台运行的一项服务,它使用 HTTP(S) 并将页面呈现为 JSON,包括您可能需要的任何元数据。

【讨论】:

【参考方案6】:

取决于 ajax 页面。屏幕抓取的第一部分是确定页面的工作方式。是否有某种变量可以迭代以从页面请求所有数据?我个人使用Web Scraper Plus 完成了很多与屏幕抓取相关的任务,因为它价格便宜,入门不难,非程序员也可以相对快速地使用它。

旁注:使用条款可能是您在执行此操作之前可能需要检查的地方。根据站点的不同,遍历所有内容可能会引发一些标志。

【讨论】:

【参考方案7】:

我认为当源代码易于阅读时,Brian R. Bondy 的回答很有用。我更喜欢使用 Wireshark 或 HttpAnalyzer 等工具来捕获数据包并从“Host”字段和“GET”字段获取 url。

例如,我捕获如下数据包:

GET /hqzx/quote.aspx?type=3&market=1&sorttype=3&updown=up&page=1&count=8&time=164330 
 HTTP/1.1
Accept: */*
Referer: http://quote.hexun.com/stock/default.aspx
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Host: quote.tool.hexun.com
Connection: Keep-Alive

那么网址就是:

http://quote.tool.hexun.com/hqzx/quote.aspx?type=3&market=1&sorttype=3&updown=up&page=1&count=8&time=164330

【讨论】:

【参考方案8】:

作为一种低成本的解决方案,您还可以尝试SWExplorerAutomation (SWEA)。该程序为使用 HTML、DHTML 或 AJAX 开发的任何 Web 应用程序创建自动化 API。

【讨论】:

【参考方案9】:

Selenium WebDriver 是一个很好的解决方案:您编写浏览器并自动执行需要在浏览器中完成的操作。浏览器(Chrome、Firefox 等)提供了自己的与 Selenium 一起工作的驱动程序。由于它作为自动 REAL 浏览器工作,因此页面(包括 javascript 和 Ajax)会像使用该浏览器的人一样被加载。

缺点是速度很慢(因为您很可能希望等待所有图像和脚本加载完毕,然后再对单个页面进行抓取)。

【讨论】:

【参考方案10】:

我之前链接到 MIT 的溶剂和 EnvJS 作为我刮掉 Ajax 页面的答案。这些项目似乎不再可用。

出于绝对必要,我发明了另一种实际刮掉 Ajax 页面的方法,它适用于像 findthecompany 这样具有查找无头 javascript 引擎并且不显示数据的方法的棘手网站。

技术是使用 chrome 扩展来进行抓取。 Chrome 扩展是删除 Ajax 页面的最佳位置,因为它们实际上允许我们访问 javascript 修改的 DOM。技术如下,我一定会在某个时候开源代码。创建一个 chrome 扩展(假设您知道如何创建一个,以及它的架构和功能。这很容易学习和实践,因为有很多示例),

    使用内容脚本通过 xpath 访问 DOM。几乎可以将整个列表或表格或使用 xpath 动态呈现的内容作为字符串 HTML 节点放入变量中。 (只有内容脚本可以访问 DOM,但不能使用 XMLHTTP 联系 URL) 从内容脚本,使用消息传递,将整个剥离的 DOM 作为字符串发送到后台脚本。 (后台脚本可以与 URL 对话,但不能接触 DOM)。我们使用消息传递来让这些人说话。 您可以使用各种事件循环浏览网页并将每个剥离的 HTML 节点内容传递给后台脚本。 现在使用后台脚本与外部服务器(在本地主机上)对话,这是一个使用 Nodejs/python 创建的简单服务器。只需将整个 HTML 节点作为字符串发送到服务器,服务器会将发布到它的内容保存到文件中,并使用适当的变量来识别页码或 URL。 现在您已经抓取了 AJAX 内容(HTML 节点作为字符串),但这些是部分 html 节点。现在,您可以使用自己喜欢的 XPATH 库将它们加载到内存中,并使用 XPATH 将信息抓取到表格或文本中。

如果你看不懂请评论,我会写得更好。 ( 第一次尝试 )。另外,我正在尝试尽快发布示例代码。

【讨论】:

以上是关于你如何抓取 AJAX 页面?的主要内容,如果未能解决你的问题,请参考以下文章

HTML 页面抓取

C#利用phantomJS抓取AjAX动态页面

scrapy实战4抓取ajax动态页面(以糗事百科APP为例子):

当 url 保持不变(但给出 ajax 响应)时,Web 抓取多个页面

Javascript爬虫

如何通过wireshark 抓取 jquery的ajax请求数据包