您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Lists all of your reviews with vote and comment tallies
当前为
/*=====================================================================================*\ | The Amazon Review Tabulator - TART | | (c) 2016 by Another Floyd | | From your "Public Reviews Written by You" page on Amazon, this script collects and | | tabulates vote tallies and related information, from all of your Amazon reviews. | \*=====================================================================================*/ // ==UserScript== // @name The Amazon Review Tabulator - TART // @namespace floyd.scripts // @version 1.0.1 // @author Another Floyd at Amazon.com // @description Lists all of your reviews with vote and comment tallies // @include https://www.amazon.com/gp/cdp/member-reviews/* // @grant GM_getValue // @grant GM_setValue // @grant GM_xmlhttpRequest // @grant GM_log // ==/UserScript== // Start (function() { var userId = ""; var reviewCount = 0; var reviewerRanking = ""; var helpfulVotes = 0; var urlStart = ""; var urlEnd = ""; var displayBuffer = ""; var oldStoreItemIDs = []; var oldStoreUpvotes = []; var oldStoreDownvotes = []; var oldStoreComments = []; // if I ever get this to open in a new window, instead of overwriting the Amazon // window, items below should be cleared at start of tabulate(), so that repeated runs // will work without error var newStoreItemIDs = ""; var newStoreUpvotes = ""; var newStoreDownvotes = ""; var newStoreComments = ""; var tallyUpvotes = 0; var tallyDownvotes = 0; var tallyStars = 0; var tallyComments = 0; function tabulate() { // set up top of display page displayBuffer += "<style type='text/css'> \ .tg {border-collapse:collapse;border-spacing:0} \ .tg td{font-family:Arial, sans-serif;font-size:12px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal} \ .tg th{font-family:Arial, sans-serif;font-size:12px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal} \ .tg .header-left{font-weight:bold;background-color:#010066;color:#ffffff;text-align:left} \ .tg .header-right{font-weight:bold;background-color:#010066;color:#ffffff;text-align:right} \ .tg .cell-left{text-align:left} \ .tg .cell-right{text-align:right} \ .tg .hilite-left{text-align:left;background-color:#FFFF12} \ .tg .hilite-right{text-align:right;background-color:#FFFF12} \ </style> \ <span style='font-size:16px;font-weight:bold'>Amazon Review Details</span><br> \ <span style='font-size:8px'>Prepared with The Amazon Review Tabulator - TART</span> \ <p>Top Reviewer Ranking: " + reviewerRanking + "<br> \ Reviews Available: " + reviewCount + "<br> \ Helpful Votes: " + helpfulVotes + "<br> \ Upvote/Review Ratio: " + (helpfulVotes/reviewCount).toFixed(2) + "<br></p> \ <table class='tg'> \ <tr><th class='header-left'>#</th><th class='header-left'>Item</th><th class='header-left'>Date</th><th class='header-right'>Stars<br></th><th class='header-right'>Upvotes</th><th class='header-right'>Downvotes</th><th class='header-right'>% Helpful<br></th><th class='header-right'>Comments</th></tr>"; // read in stored info from past run, for use in change detection oldStoreItemIDs = GM_getValue("recentItemIDs", "").split(" "); oldStoreUpvotes = GM_getValue("recentUpvotes", "").split(" "); oldStoreDownvotes = GM_getValue("recentDownvotes", "").split(" "); oldStoreComments = GM_getValue("recentComments", "").split(" "); // prepare url with user ID, ready for review page number urlStart = "https://www.amazon.com/gp/cdp/member-reviews/" + userID + "?ie=UTF8&display=public&page="; urlEnd = "&sort_by=MostRecentReview"; // lots of page loading and data retrieval var perPageResponseDiv = []; var pageResponseCount = 0; var reviewsProcessed = 0; var pageCount = Math.floor(reviewCount / 10) + ((reviewCount % 10 > 0) ? 1 : 0); //var pageCount = 2; // for testing var x = 1; while (x <= pageCount) { (function(x){ var urlComplete = urlStart + x + urlEnd; perPageResponseDiv[x] = document.createElement('div'); GM_xmlhttpRequest({ method: "GET", url: urlComplete, onload: function(response) { perPageResponseDiv[x].innerHTML = response.responseText; pageResponseCount++; // see if all data from multiple page loads has arrived if(pageResponseCount==pageCount) { for(y = 1; y <= pageCount; y++) { // get parent of any reviewText DIV var findReviews = document.evaluate("//div[@class='reviewText']/..", perPageResponseDiv[y], null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); // evaluating the doc DIV made above for (var j = 0; j < findReviews.snapshotLength; j++) { var oneReview = findReviews.snapshotItem(j); var reviewChildren = oneReview.children; var childCount = reviewChildren.length; var commentCount = 0; var itemTitle = ""; var itemLink = ""; var permaLink = ""; var starRating = 0; var reviewDate = ""; var upVotes = 0; var downVotes = 0; var itemID = ""; // get number of comments, and permalink var tempText = reviewChildren[childCount-2].textContent; if(tempText.indexOf('Comment (') > -1 || tempText.indexOf('Comments (') > -1) { var paren1 = tempText.indexOf('('); var paren2 = tempText.indexOf(')'); commentCount = tempText.substring(paren1+2,paren2-1); } var lst = reviewChildren[childCount-2].getElementsByTagName('a'); permaLink = lst[2].getAttribute("href"); // get item title and item link var lst = reviewChildren[childCount-4].getElementsByTagName('a'); itemLink = lst[0].getAttribute("href"); itemTitle = lst[0].textContent; // the top few items to retrieve are done in a loop with IF checks, // because the number of entries above the review varies, depending on // whether there have been votes, if it's a verified purchase, etc. for (var i = childCount - 5; i > -1; i--) { // get star rating AND review date var childHTML = reviewChildren[i].innerHTML; var ratingClue = childHTML.indexOf('out of 5 stars'); if(ratingClue > -1) { starRating = childHTML.substring(ratingClue-4,ratingClue-1); reviewDate = reviewChildren[i].lastElementChild.textContent; } // get vote counts var childText = reviewChildren[i].textContent; var voteClue = childText.indexOf('people found the following review helpful'); if(voteClue > -1) { var list = childText.trim().split(" "); // there were extra, invisible spaces! upVotes = list[0]; var totalVotes = list[2]; downVotes = totalVotes - upVotes; } } // get item ID var lst = oneReview.parentNode.getElementsByTagName('a'); itemID = lst[0].getAttribute("name"); // get HTML formatted table row displayBuffer += prepOneTableRow((j+1+(y-1)*10),itemID,itemTitle,permaLink,reviewDate,starRating,upVotes,downVotes,commentCount); reviewsProcessed++; } } // add footer and complete results page displayBuffer += "<tr><td class='header-left'></td><td class='header-left'></td><td class='header-left'></td><td class='header-right'>" + (tallyStars/reviewsProcessed).toFixed(1) + "</td><td class='header-right'>" + tallyUpvotes + "</td><td class='header-right'>" + tallyDownvotes + "</td><td class='header-right'>" + helpfulPercent(tallyUpvotes,tallyDownvotes) + "</td><td class='header-right'>" + tallyComments + "</td></tr></table>"; // store info to be used in subsequent run, for change detection GM_setValue("recentItemIDs", newStoreItemIDs.trim()); GM_setValue("recentUpvotes", newStoreUpvotes.trim()); GM_setValue("recentDownvotes", newStoreDownvotes.trim()); GM_setValue("recentComments", newStoreComments.trim()); // display results page document.body.innerHTML = displayBuffer; } } }); })(x); x++; } } function helpfulPercent(upVotes,downVotes) { var helpfulPercent = ""; upVotes = parseInt(upVotes); downVotes = parseInt(downVotes); if(upVotes + downVotes > 0) helpfulPercent = (upVotes/(upVotes+downVotes)*100).toFixed(1); return helpfulPercent; } function prepOneTableRow (row,itemID,itemTitle,permaLink,reviewDate,starRating,upVotes,downVotes,commentCount) { // do these before mangling the values with <b> tags </b> var helpfulPct = helpfulPercent(upVotes,downVotes); itemTitle = "<a href='" + permaLink + "' target='_new'>" + itemTitle.substring(0,65) + "</a>"; // keep tallies to use in table footer tallyUpvotes += parseInt(upVotes); tallyDownvotes += parseInt(downVotes); tallyStars += parseInt(starRating); tallyComments += parseInt(commentCount); // assemble storage info, to use in subsequent run, for change detection newStoreItemIDs += itemID + " "; newStoreUpvotes += upVotes + " "; newStoreDownvotes += downVotes + " "; newStoreComments += commentCount + " "; // see if review for this item has previously been examined var matchIdx = -1; for(var i=0; i<oldStoreItemIDs.length; i++) { if(oldStoreItemIDs[i] == itemID) { // we have a match, an item that has previously been seen matchIdx = i; break; } } var hiliteRow = false; if(matchIdx > -1) { // entry exists; see if any of the numbers have changed if(oldStoreUpvotes[matchIdx] != upVotes) { // for changed number, make it bold, and hilite row upVotes = "<b>" + upVotes + "</b>"; hiliteRow = true; } if(oldStoreDownvotes[matchIdx] != downVotes) { downVotes = "<b>" + downVotes + "</b>"; hiliteRow = true; } if(oldStoreComments[matchIdx] != commentCount) { commentCount = "<b>" + commentCount + "</b>"; hiliteRow = true; } } else { // no match, so, it's a new review; bold the title and hilite the row itemTitle = "<b>" + itemTitle + "</b>"; hiliteRow = true; } var tdLeft = ((hiliteRow===true)? "<td class='hilite-left'>" : "<td class='cell-left'>"); var tdRight = ((hiliteRow===true)? "<td class='hilite-right'>" : "<td class='cell-right'>"); var tableRow = "<tr>" + tdLeft + row + "</td>" + tdLeft + itemTitle + "</td>" + tdLeft + reviewDate + "</td>" + tdRight + starRating + "</td>" + tdRight + upVotes + "</td>" + tdRight + downVotes + "</td>" + tdRight + helpfulPct + "</td>" + tdRight + commentCount + "</td></tr>"; return tableRow; } //--- global event listeners allow working across scopes document.addEventListener('click', function(event) { var tempstr = new String(event.target); if(tempstr.indexOf('tabulate') > -1) { tabulate(); event.stopPropagation(); event.preventDefault(); } }, true); //--- main script block from this point function Tabulate_Amazon_Reviews_Run() { // find profile info panel var findDiv = document.evaluate("//div[contains(.,'Helpful Votes')]", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); var profileDiv = findDiv.snapshotItem(0); // get reviewer ranking and user ID var lst = profileDiv.getElementsByTagName('a'); reviewerRanking = lst[0].textContent; var charIdx = lst[0].getAttribute("href").indexOf('#'); userID = lst[0].getAttribute("href").substring(charIdx+1); // get helpful votes charIdx = profileDiv.textContent.lastIndexOf(':'); helpfulVotes = profileDiv.textContent.substring(charIdx+2); // get review count var prevSibDiv = profileDiv.previousElementSibling; charIdx = prevSibDiv.textContent.lastIndexOf(':'); reviewCount = prevSibDiv.textContent.substring(charIdx+2); // add Tabulate link profileDiv.innerHTML += "<br></br><a href='javascript:tabulate();'>Tabulate</a>"; } Tabulate_Amazon_Reviews_Run(); })(); // End
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址