您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Utility library for grabbing info from rottentomatoes.com
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/389810/731014/RottenTomatoes%20Utility%20Library.js
// ==UserScript== // @name RottenTomatoes Utility Library // @namespace driver8.net // @version 0.1.1 // @description Utility library for grabbing info from rottentomatoes.com // @author driver8 // @grant GM_xmlhttpRequest // @connect rottentomatoes.com // ==/UserScript== console.log('hi rt'); var MAX_YEAR_DIFF = 2; function _parse(query, regex, doc) { doc = doc || document; try { let text = doc.querySelector(query).textContent.trim(); if (regex) { text = text.match(regex)[1]; } return text.trim(); } catch (e) { console.log('error', e); return ''; } }; function getRtIdFromTitle(title, tv, year) { tv = tv || false; year = parseInt(year) || 1800; return new Promise(function(resolve) { GM_xmlhttpRequest({ method: 'GET', responseType: 'json', url: 'https://www.rottentomatoes.com/api/private/v2.0/search/?limit=10&q=' + title, onload: (resp) => { let movies = tv ? resp.response.tvSeries : resp.response.movies; let sorted = movies.concat(); if (year) { sorted.sort((a, b) => { if (Math.abs(a.year - year) !== Math.abs(b.year - year)) { // Prefer closest year to the given one return Math.abs(a.year - year) - Math.abs(b.year - year); } else { return b.year - a.year; // In a tie, later year should come first } }); } // Search for matches with exact title in order of proximity by year let bestMatch; for (let m of sorted) { m.title = m.title || m.name; if (m.title.toLowerCase() === title.toLowerCase()) { bestMatch = m; break; } } //console.log('sorted', sorted, 'bestMatch', bestMatch, movies); // Fall back on closest year match if with 2 years, or whatever the first result was. bestMatch = bestMatch || (sorted && Math.abs(sorted[0].year - year) <= MAX_YEAR_DIFF && sorted[0]) || (movies && movies[0]); let id = bestMatch.url.replace(/\/s\d{2}\/?$/, ''); // remove season suffix from tv matches console.log('found id', id); resolve(id); } }); }); } function getRtInfoFromId(id) { return new Promise(function(resolve) { let url = 'https://www.rottentomatoes.com' + id + (id.startsWith('/tv/') ? '/s01' : ''); // Look up season 1 for TV shows GM_xmlhttpRequest({ method: 'GET', responseType: 'document', url: url, onload: (resp) => { let text = resp.responseText; // Create DOM from responseText const doc = document.implementation.createHTMLDocument().documentElement; doc.innerHTML = text; let year = parseInt(_parse('.h3.year, .movie_title .h3.subtle, .meta-row .meta-value time', /(\d{4})/, doc)); // Find the javascript snippet storing the tomatometer/score info. // Everything is named different for TV shows for some stupid reason. let m = text.match(/root\.RottenTomatoes\.context\.scoreInfo = ({.+});/); m = m || text.match(/root\.RottenTomatoes\.context\.scoreboardCriticInfo = ({.+});/); let dataString = m[1]; let scoreInfo = JSON.parse(dataString); let all = scoreInfo.tomatometerAllCritics || scoreInfo.all || {}, top = scoreInfo.tomatometerTopCritics || scoreInfo.top || {}; //console.log('scoreInfo', scoreInfo); // TV consensus is stored in a totally different object :/ m = text.match(/root\.RottenTomatoes\.context\.result = ({.+});/); let contextResult = m && JSON.parse(m[1]); // Try field names used for movie data, then TV show data. const data = { id: id, score: all.score || all.tomatometer, rating: all.avgScore || all.averageRating, votes: all.numberOfReviews || all.totalCount, consensus: all.consensus || (contextResult && contextResult.seasonData && contextResult.seasonData.tomatometer.consensus), // TV consensus is stored in a totally different object :/ state: all.tomatometerState || all.state, topScore: top.score || top.tomatometer, topRating: top.avgScore || top.averageRating, topVotes: top.numberOfReviews || top.totalCount, year: year, fetched: new Date() }; console.log('found data', data); resolve(data); } }); }); } function getRtInfoFromTitle(title, tv, year) { return getRtIdFromTitle(title, tv, year).then((id) => { return getRtInfoFromId(id); }) }