我正在与世界银行合作开展一个项目,分析他们的采购流程。
世界银行为其每个项目维护网站,其中包含已发布的相关合同的链接和数据(示例)。采购选项卡下提供与合同相关的数据。
我希望能够从该站点提取项目的合同信息,但链接和相关数据是使用嵌入式 Javascript 生成的,并且显示合同授予和其他数据的页面的 URL 似乎没有遵循可识别的模式(示例)。
有什么方法可以通过 R 在第一个示例中抓取浏览器呈现的数据?
主页面调用一个javascript函数
javascript:callTabContent('p','P090644','','en','procurement','procurementId');
这里主要的是项目 id P090644
。这与所需的语言一起en
作为参数传递给http://www.worldbank.org/p2e/procurement.html上的表单。
可以使用 URL http://www.worldbank.org/p2e/procurement.html?lang=en&projId=P090644复制此表单调用。
提取相关项目描述 url 的代码如下:
projID<-"P090644"
projDetails<-paste0("http://www.worldbank.org/p2e/procurement.html?lang=en&projId=",projID)
require(XML)
pdData<-htmlParse(projDetails)
pdDescribtions<-xpathSApply(pdData,'//*/table[@id="contractawards"]//*/@href')
#> pdDescribtions
href
#"http://search.worldbank.org/wcontractawards/procdetails/OP00005718"
href
#"http://search.worldbank.org/wcontractawards/procdetails/OP00005702"
href
#"http://search.worldbank.org/wcontractawards/procdetails/OP00005709"
href
#"http://search.worldbank.org/wcontractawards/procdetails/OP00005715"
应该注意的是,提供了可能对您有用的 excel 链接。它们可能包含您打算从描述链接中删除的数据
procNotice<-paste0("http://search.worldbank.org/wprocnotices/projectdetails/",projID,".xls")
conAward<-paste0("http://search.worldbank.org/wcontractawards/projectdetails/",projID,".xls")
conData<-paste0("http://search.worldbank.org/wcontractdata/projectdetails/",projID,".xls")
require(gdata)
pnData<-read.xls(procNotice)
caData<-read.xls(conAward)
cdData<-read.xls(conData)
更新:
要查找发布的内容,我们可以检查调用 javascript 函数时发生的情况。使用 Firebug 或类似的东西,我们拦截了开始的请求标头:
POST /p2e/procurement.html HTTP/1.1
Host: www.worldbank.org
并有参数:
lang=en
projId=P090644
或者,我们可以在http://siteresources.worldbank.org/cached/extapps/cver116/p2e/js/script.js检查 javascript并查看函数callTabContent
:
function callTabContent(tabparam, projIdParam, contextPath, langCd, htmlId, anchorTagId) {
if (tabparam == 'n' || tabparam == 'h') {
$.ajax( {
type : "POST",
url : contextPath + "/p2e/"+htmlId+".html",
data : "projId=" + projIdParam + "&lang=" + langCd,
success : function(msg) {
if(tabparam=="n"){
$("#newsfeed").replaceWith(msg);
} else{
$("#cycle").replaceWith(msg);
}
stickNotes();
}
});
} else {
$.ajax( {
type : "POST",
url : contextPath + "/p2e/"+htmlId+".html",
data : "projId=" + projIdParam + "&lang=" + langCd,
success : function(msg) {
$("#tabContent").replaceWith(msg);
$('#map_container').hide();
changeAlternateColors();
$("#tab_menu a").removeClass("selected");
$('#'+anchorTagId).addClass("selected");
stickNotes();
}
});
}
}
检查函数的内容,我们可以看到它只是将相关参数发布到表单然后更新网页。
我不确定我是否了解您问题的所有细节。但我可以肯定的是,casperJS 非常适合 javascript 生成的内容。
你可以在这里看看:http ://casperjs.org/
它是用 Javascript 编写的,并且在我提供的链接上很好地记录了许多有用的功能。
我最近自己将它用于个人项目,只需几行代码即可轻松设置。
搏一搏!希望,这有帮助..