Greasemonkey可以从分页的URL序列中获取值吗?

我想从https://play.google.com/store/account*获取一个值,该值会使用户页面通过其输出。 例如:
/store/account?start=0&num=40 ,then /store/account?start=40&num=40

现在,当我访问https://play.google.com/apps ,我希望Greasemonkey汇总/store/account页面中的值,然后在该页面上显示最终值。

下面列出的代码可以从/store/account页面总计我想要的值。 但是,我想将代码插入到用于第二个URL的脚本中,因此我可以将其添加到同一页面上。

 // ==UserScript== // @name Google Play // @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js // @grant GM_setValue // @grant GM_getValue // ==/UserScript== var startParam = location.search.match (/\bstart=(\d+)/i); if (startParam) { var totalPrice = 0; var startNum = parseInt (startParam[1], 10); if (startNum === 0) { GM_setValue ("TotalPrice", "0"); } else { totalPrice = parseFloat (GM_getValue ("TotalPrice", 0) ); } $("#tab-body-account .rap-link").each( function () { var price = $(this).attr ("data-docprice").replace (/[^\d\.]/g, ""); if (price) { price = parseFloat (price); if (typeof price === "number") { totalPrice += price; } } } ); //console.log ("totalPrice: ", totalPrice.toFixed(2) ); $('.tabbed-panel-tab').before ( '
*Combined Value: $'+ totalPrice.toFixed(2) +'
' ); GM_setValue ("TotalPrice", "" + totalPrice); if ( $(".snippet.snippet-tiny").length ) { startNum += 40; var nextPage = location.href.replace ( /\bstart=\d+/i, "start=" + startNum ); location.assign (nextPage); } }

从mashup的页面/站点获取数据的基本方法是:

  1. 通过AJAX刮刮:
    这适用于几乎所有页面,但它不适用于通过AJAX加载所需内容的页面。 有时,对于需要身份validation或限制引荐来源的网站来说,它也会变得棘手。
    在大多数情况下使用GM_xmlhttpRequest()以允许跨域脚本编写。 这种方法将在下面详述。

  2. 加载资源页面:
    这种方法适用于AJAX-ified页面,并且可以编码以让用户手动处理登录问题。 但是,这是:速度更慢,资源更密集,代码更复杂。

    由于此问题的详细信息似乎不需要,请参阅“如何在返回响应之前获取AJAX get-request以等待页面呈现?” 有关此技术的更多信息。

  3. 使用网站的API,如果有的话:
    唉,大多数网站都没有API,所以这可能不适合您,但值得确保不提供API。 如果API可用,API通常是最好的方法。 有关此方法的更多详细信息,请执行新的搜索/问题。

  4. 模仿网站的AJAX调用,如果它调用了你想要的那种信息:
    此选项也不适用于大多数站点,但它可以是一种干净,高效的技术。 有关此方法的更多详细信息,请执行新的搜索/问题。


通过具有跨域function的AJAX从一系列网页中获取值:

使用GM_xmlhttpRequest()加载页面,使用jQuery处理HTML。
使用GM_xmlhttpRequest()onload函数调用下一页,如果需要,不要尝试使用同步AJAX调用。

原始脚本中的核心逻辑移动到onload函数中 – 除了不再需要记住Greasemonkey运行之间的值。

这是一个完整的Greasemonkey脚本 ,其中包含一些状态和错误报告:

 // ==UserScript== // @name _Total-value mashup // @include https://play.google.com/apps* // @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js // @grant GM_addStyle // @grant GM_xmlhttpRequest // ==/UserScript== var startNum = 0; var totalValue = 0; //--- Scrape the first account-page for item values: $("body").prepend ( '
Fetching total value, please wait...
' ); scrapeAccountPage (); function scrapeAccountPage () { var accntPage = 'https://play.google.com/store/account?start=0&num=40'; accntPage = accntPage.replace (/start=\d+/i, "start=" + startNum); $("#gm_statusBar").append ( 'Fetching page ' + accntPage + '...' ); GM_xmlhttpRequest ( { method: 'GET', url: accntPage, //--- getTotalValuesFromPage() also gets the next page, as appropriate. onload: getTotalValuesFromPage, onabort: reportAJAX_Error, onerror: reportAJAX_Error, ontimeout: reportAJAX_Error } ); } function getTotalValuesFromPage (respObject) { if (respObject.status != 200 && respObject.status != 304) { reportAJAX_Error (respObject); return; } $("#gm_statusBar").append ('done.'); var respDoc = $(respObject.responseText); var targetElems = respDoc.find ("#tab-body-account .rap-link"); targetElems.each ( function () { var itmVal = $(this).attr ("data-docprice").replace (/[^\d\.]/g, ""); if (itmVal) { itmVal = parseFloat (itmVal); if (typeof itmVal === "number") { totalValue += itmVal; } } } ); console.log ("totalValue: ", totalValue.toFixed(2) ); if ( respDoc.find (".snippet.snippet-tiny").length ) { startNum += 40; //--- Scrape the next page. scrapeAccountPage (); } else { //--- All done! report the total. $("#gm_statusBar").empty ().append ( 'Combined Value: $' + totalValue.toFixed(2) ); } } function reportAJAX_Error (respObject) { $("#gm_statusBar").append ( 'Error ' + respObject.status + '!   ' + '"' + respObject.statusText + '"    ' + 'Total value, so far, was: ' + totalValue + '' ); } //--- Make it look "purty". GM_addStyle ( multilineStr ( function () {/*! #gm_statusBar { margin: 0; padding: 1.2ex; font-family: trebuchet ms,arial,sans-serif; font-size: 18px; border: 3px double gray; border-radius: 1ex; box-shadow: 1ex 1ex 1ex gray; color: black; background: lightgoldenrodyellow; } #gm_statusBar .gmStatStart { font-size: 0.5em; margin-left: 3em; } #gm_statusBar .gmStatFinish { font-size: 0.5em; background: lime; } #gm_statusBar .gmStatError { background: red; white-space: nowrap; } */} ) ); function multilineStr (dummyFunc) { var str = dummyFunc.toString (); str = str.replace (/^[^\/]+\/\*!?/, '') // Strip function() { /*! .replace (/\s*\*\/\s*\}\s*$/, '') // Strip */ } .replace (/\/\/.+$/gm, '') // Double-slash comments wreck CSS. Strip them. ; return str; }


重要提示:不要忘记@include @match@match和/或@match指令,因此您的脚本不会在每个页面和iframe上运行!