请告知如何抓取 AJAX 页面。
10 回答
概述:
所有屏幕抓取首先需要手动查看您要从中提取资源的页面。在处理 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 请求。 来自 w3schools 的示例。
使用 C++ 进行高级抓取:
对于复杂的用法,如果您使用 C++,您还可以考虑使用 firefox javascript 引擎SpiderMonkey在页面上执行 javascript。
使用 Java 进行高级抓取:
对于复杂的使用,如果您使用 Java,您还可以考虑使用适用于 Java Rhino的 firefox javascript 引擎
使用 .NET 进行高级抓取:
对于复杂的使用,如果您使用的是 .Net,您还可以考虑使用 Microsoft.vsa 程序集。最近替换为 ICodeCompiler/CodeDOM。
在我看来,最简单的解决方案是使用Casperjs,这是一个基于 WebKit 无头浏览器 phantomjs 的框架。
整个页面加载完毕,很容易抓取任何与 ajax 相关的数据。您可以查看这个基本教程来学习使用 PhantomJS 和 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();
});
如果可以,请尝试检查 DOM 树。Selenium将其作为测试页面的一部分。它还具有单击按钮和跟踪链接的功能,这可能很有用。
使用 Ajax 或一般使用 Javascript 抓取网页的最佳方法是使用浏览器本身或无头浏览器(没有 GUI 的浏览器)。目前phantomjs是一个使用 WebKit 的很好的无头浏览器。我成功使用的替代方法是HtmlUnit(在 Java 或 .NET 中通过IKVM,这是一个模拟浏览器。另一个已知的替代方法是使用 Web 自动化工具,如Selenium。
我写了很多关于这个主题的文章,比如网页抓取 Ajax 和 Javascript 站点以及Twitter 的自动无浏览器 OAuth 身份验证。在第一篇文章的最后,有很多我从 2011 年开始编译的额外资源。
我喜欢PhearJS,但这可能部分是因为我构建了它。
也就是说,它是您在后台运行的服务,它使用 HTTP(S) 并将页面呈现为 JSON,包括您可能需要的任何元数据。
取决于ajax页面。屏幕抓取的第一部分是确定页面的工作方式。是否有某种变量可以迭代以从页面请求所有数据?就我个人而言,我使用Web Scraper Plus完成了很多与屏幕抓取相关的任务,因为它价格便宜,上手不难,非程序员可以相对快速地使用它。
旁注:使用条款可能是您在执行此操作之前可能要检查的地方。根据站点的不同,遍历所有内容可能会引发一些标志。
我认为当源代码易于阅读时,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
作为低成本解决方案,您还可以尝试SWExplorerAutomation (SWEA)。该程序为使用 HTML、DHTML 或 AJAX 开发的任何 Web 应用程序创建自动化 API。
Selenium WebDriver 是一个很好的解决方案:您编写浏览器并自动执行需要在浏览器中完成的操作。浏览器(Chrome、Firefox 等)提供了自己的与 Selenium 一起使用的驱动程序。由于它作为一个自动化的REAL 浏览器工作,因此页面(包括 javascript 和 Ajax)会像使用该浏览器的人一样被加载。
缺点是它很慢(因为您很可能希望在对单个页面进行抓取之前等待所有图像和脚本加载)。
我以前链接到 MIT 的溶剂和 EnvJS 作为我刮掉 Ajax 页面的答案。这些项目似乎不再可用。
出于绝对必要,我发明了另一种实际刮掉 Ajax 页面的方法,它适用于像 findthecompany 这样具有查找无头 javascript 引擎并且不显示数据的方法的棘手网站。
该技术是使用 chrome 扩展来进行抓取。Chrome 扩展是删除 Ajax 页面的最佳位置,因为它们实际上允许我们访问 javascript 修改的 DOM。技术如下,我一定会在某个时候开源代码。创建一个 chrome 扩展(假设您知道如何创建一个,以及它的架构和功能。这很容易学习和实践,因为有很多示例),
- 通过使用 xpath 使用内容脚本来访问 DOM。几乎可以将整个列表或表格或使用 xpath 动态呈现的内容作为字符串 HTML 节点放入变量中。(只有内容脚本可以访问 DOM,但它们不能使用 XMLHTTP 联系 URL)
- 从内容脚本,使用消息传递,将整个剥离的 DOM 作为字符串发送到后台脚本。(后台脚本可以与 URL 对话,但不能接触 DOM)。我们使用消息传递来让这些对话。
- 您可以使用各种事件循环浏览网页并将每个剥离的 HTML 节点内容传递给后台脚本。
- 现在使用后台脚本与外部服务器(在 localhost 上)对话,这是一个使用 Nodejs/python 创建的简单服务器。只需将整个 HTML 节点作为字符串发送到服务器,服务器会将发布到它的内容保存到文件中,并使用适当的变量来识别页码或 URL。
- 现在您已经抓取了 AJAX 内容(HTML 节点作为字符串),但这些是部分 html 节点。现在,您可以使用您最喜欢的 XPATH 库将这些加载到内存中,并使用 XPATH 将信息抓取到表格或文本中。
如果您看不懂,请发表评论,我可以写得更好。( 第一次尝试 )。另外,我正在尝试尽快发布示例代码。