我正在为该站点(Site1)中的页面编写Greasemonkey脚本。Site1提供各种交易和报价,而我的GM脚本旨在实现以下目的:
当一个人访问Site1上的报价时,脚本会查询 Site2,以查找该酒店是否也在Site2上列出。如果是这样,请在Site1上显示来自Site2的搜索结果。
问题是Site2显示进度条(“正在加载结果”),然后显示结果。因此,我的Ajax请求始终返回空结果,并且看起来像这样(请参见红色框部分):( 单击查看大图)
但是,它实际上应该具有Site2的搜索结果的完整内容,如下所示:( 单击以查看大图)
我尝试了同步Ajax请求GM_xmlhttpRequest,但无济于事。
GM_xmlhttpRequest
这是站点2出现问题的进度条:( 单击查看大图)
在将响应返回给Site1之前,如何获得AJAX请求以等待对Site2的搜索完全呈现?
作为参考,我完整的工作脚本代码在pastebin.com上。
这是相关的代码段:
$(document).ready(function(){ var rewardsSiteResults = $('<div class="panel deal-panel rc-lr"></div>').attr('id', "rewardsSiteResults") .html("<p>" + progressMessageText + "</p> ").append(spinnerGif); $(insertSelector).after(rewardsSiteResults); var addressMap = getAddressOfHotel(); var pinCode = addressMap[pinCodePlaceHolder]; var hotelName = addressMap[hotelNamePlaceHolder]; var queryURL = constructQueryURL(pinCode, hotelName); $.ajaxSetup({async:true, timeout: 5000}); $.get(queryURL,null, function(response) { if(!displayed){ displayed=true; //rewardsSiteResults.html("adfaasddsf"); var text = $(response).find("#col2"); $(text).find("script").remove(); //console.log(text.html()) // $('<iframe id="someId"/>').appendTo('#rewardsSiteResults') // .contents().find('body').append(response); rewardsSiteResults.html("<div class='panel deal-panel rc-lr'>" + text.html() +"</div>"); //console.log(response); } },'html'); });
为了使AJAX“等待页面呈现”,它实际上必须完全处理页面, 并 获取 并运行 所有包含的CSS和javascript文件。这并不容易,不建议这样做。幸运的是,您仍然不需要这样做。
这是解决此类问题的三种更好的方法:
在 资源页面 (mpdining.rewardsnetwork.com,对于这个问题),可能有一个API。如果有,请找到并使用它。如果可以的话,这是您最好的选择。
分析资源页面的javascript和/或AJAX请求。使用GM_xmlhttpRequest()直接取刚刚有效载荷数据,而不是试图解析资源页面。
GM_xmlhttpRequest()
有时,此过程相当容易,但是某些站点需要复杂的交互和/或身份验证。
postMessage()
尽管您可能必须防止某些页面试图从iframe中“退出”,但是这种方法几乎总是可行的。
Greasemonkey脚本将在普通页面和iframe内的页面上运行。实际上,您可以将同一脚本设置为同时在多个域和两个域上运行。
如果 母版页 和iframed 资源页 都运行GM脚本,则脚本实例可以使用跨域相互通信postMessage()。
例如,假设我们有一个网站,fiddle.jshell.net/9ttvF/show,包含旅游数据,我们要 混搭了 该网站与从匹配数据 资源网站 ,jsbin.com/ahacab,使用AJAX获得其有效载荷数据。
目标(主)站点如下所示:
首先,资源站点如下所示:
然后完成如下:
以下脚本:
然后,目标页面的脚本会插入有效载荷数据以完成混搭。
// ==UserScript== // @name _Cross-site, AJAX scrape demo // @include http://fiddle.jshell.net/9ttvF/show/ // @include http://jsbin.com/ahacab* // @require http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js // @require https://gist.github.com/raw/2625891/waitForKeyElements.js // @grant GM_addStyle // ==/UserScript==
if (/fiddle.jshell.net/i.test (location.host) ) { console.log (“***Master-page start…”);
/*--- Inform the user. */ $("#plainResults").before ( '<div id="gmFetchRez">Greasemonkey is fetching results from jsbin.com...</div>' ); /*--- Setup to process messages from the GM instance running on the iFrame: */ window.addEventListener ("message", receiveMessage, false); /*--- Load the resource site in a hidden iframe. */ $("body").append ('<iframe src="http://jsbin.com/ahacab" id="gmIframe"></iframe>');
} else { console.log (“*Framed start…”); /— Wait for the AJAXed-in content… / waitForKeyElements (“#results table.rezTable”, sendResourcePageData); }
function sendResourcePageData (jNode) { console.log (“Results found! Sending them to the main window…”);
window.top.postMessage (jNode.html(), "*");
}
function receiveMessage (event) { if (event.origin != "http://jsbin.com”) return;
$("#gmFetchRez").html (event.data);
//— Use CSS to control appearances. GM_addStyle ( ” \ #gmIframe { \ display: none; \ } \ #gmFetchRez { \ background: lightYellow; \ border: 3px double red; \ padding: 1em; \ } \ ” );
安装并运行脚本后,最终结果如下所示: