UserScript, чтобы зациклить несколько HTTP-запросов и объединить результаты?
Теперь я знаю, как загружать столбцы таблицы с внешней веб-страницы.
Теперь я хочу остановиться на этом и:
- Извлечение табличных данных с нескольких страниц (ранжирование по позиции игрока).
- Объедините это в одну главную таблицу.
Это URL (http:...fantasysports.yahoo.com...pos=QB), который в настоящее время выбирает скрипт. Столбцы - это название команды и ранг команды для различных позиций.
Я хочу, чтобы он повторялся по другим позициям (например, WR, RB, TE). Это можно сделать, просто изменив последние 2 буквы URL на соответствующее значение. Затем я хочу, чтобы все эти данные были в одном массиве, где первый столбец - это название команды, второй столбец - это # место для позиции QB, третий столбец - это # место для позиции WR и так далее.
Мой план состоял в том, чтобы поставить GM_xmlhttpRequest
в for
цикл, который перебирает различные названия позиций.
Мой код может отображать отдельные таблицы для позиций, но по какой-то причине они не в порядке.
Другой проблемой, с которой я столкнулся, была переменная область действия. В настоящее время newStatTable
определяется внутри parseResponse
функция, но я не могу получить к ней доступ из-за пределов функции. Я пытался удалить var
от var newStatTable
сделать его глобальным, но это не сработало.
Вот пример выходного массива, который я ищу (Примечание: я просто случайно выбрал эти ранги):
TeamName QB WR TE and so on...
--- -- -- --
Jacksonville Jaguars 1 6 28
Sanfrancisco 49ers 4 2 32
Seattle Seahawks 31 5 10
Вот моя попытка.
// ==UserScript==
// @name _Grab stuff of a *static*, third-party web site.
// @include http://football.fantasysports.yahoo.com/*
// @include https://football.fantasysports.yahoo.com/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @grant GM_xmlhttpRequest
// ==/UserScript==
pos = ["QB", "WR", "RB", "TE", "K", "DEF"];
for (x in pos) {
GM_xmlhttpRequest ( {
method: "GET",
url: "http://football.fantasysports.yahoo.com/f1/326198/pointsagainst?pos=" + pos[x],
onload: parseResponse,
onerror: function (e) { console.error ('**** error ', e); },
onabort: function (e) { console.error ('**** abort ', e); },
ontimeout: function (e) { console.error ('**** timeout ', e); }
} );
}
function parseResponse (response) {
var parser = new DOMParser ();
var ajaxDoc = parser.parseFromString (response.responseText, "text/html");
var statRows = ajaxDoc.querySelectorAll ("#statTable0 > tbody > tr");
var newStatTable = $(statRows).map ( function () {
var tblRow = $(this);
var teamRank = parseInt (tblRow.find (".rank-indicator").text().trim(), 10);
var teamName = tblRow.find ("td:eq(1)").text().trim().split(" vs")[0];
return [ [teamName, teamRank] ]; //Return Teamname, Rank #
} ).get ();
console.log (newStatTable);
}
1 ответ
AJAX, по определению асинхронный. Это означает, что возвращаемые данные будут возвращаться практически в любом порядке, и данные не будут доступны вне функций обратного вызова, если вы явно не скопируете их.
Таким образом, для многостраничных гибридных приложений у вас должен быть способ сопоставления данных по мере необходимости. (В вашем случае вы можете сопоставить название команды.)
Общий подход заключается в следующем:
- Создать
Associative Array
держать данные. - Передайте контекст в каждом вызове AJAX.
- Используйте этот контекст для управления тем, как функция обратного вызова AJAX анализирует данные и объединяет их в общий массив.
- Отслеживайте состояние вызовов AJAX и выполняйте окончательную обработку только после их завершения.
Вот как это выглядит в скрипте пользователя:
// ==UserScript==
// @name _Mash up tables from several *static*, third-party, web pages.
// @match *://football.fantasysports.yahoo.com/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @grant GM_xmlhttpRequest
// ==/UserScript==
const playerPositions = ["QB", "WR", "RB", "TE", "K", "DEF"];
const numPositions = playerPositions.length;
const baseURL = "http://football.fantasysports.yahoo.com/f1/326198/pointsagainst?pos=";
var rankingsTable = {}; //-- This will be filled by the AJAX parser.
var numPagesFetched = 0;
for (var J in playerPositions) {
GM_xmlhttpRequest ( {
method: "GET",
url: baseURL + playerPositions[J],
context: playerPositions[J],
onload: parseResponse,
onerror: function (e) { console.error ('**** error ', e); },
onabort: function (e) { console.error ('**** abort ', e); },
ontimeout: function (e) { console.error ('**** timeout ', e); }
} );
}
function parseResponse (response) {
var playerPosition = response.context;
var parser = new DOMParser ();
var ajaxDoc = parser.parseFromString (response.responseText, "text/html");
var statRows = ajaxDoc.querySelectorAll ("#statTable0 > tbody > tr");
var newStatTable = $(statRows).map ( function () {
var tblRow = $(this);
var teamRank = parseInt (tblRow.find (".rank-indicator").text().trim(), 10);
var teamName = tblRow.find ("td:eq(1)").text().trim().split(" vs")[0];
return [ [teamName, teamRank] ];
} ).get ();
numPagesFetched++;
console.log ('Fetched page ' + numPagesFetched + ' of ' + numPositions + '.');
/*--- Now loop over the fetched rows and collate them into the master table, depending
on playerPosition.
*/
var columnIdx = playerPositions.indexOf (playerPosition);
for (var K in newStatTable) {
var teamName = newStatTable[K][0];
var teamRank = newStatTable[K][1];
var teamStats = rankingsTable[teamName] || new Array (numPositions);
teamStats[columnIdx] = teamRank;
rankingsTable[teamName] = teamStats;
}
if (numPagesFetched === numPositions) {
displayFinalResult ();
}
}
function displayFinalResult () {
var sortedTeamNames = Object.keys (rankingsTable).sort ( function (zA, zB) {
return zA.localeCompare (zB);
} );
const namePadStr = new Array (25).join (' ');
console.log (
'Team Ranks QB, WR, RB, TE, K, DEF\n' +
'------------------------ ------------------------------'
);
for (var J in sortedTeamNames) {
var teamName = sortedTeamNames[J];
if (rankingsTable.hasOwnProperty (teamName) ) {
console.log (
(teamName + namePadStr).slice (0, 24) + ' ', rankingsTable[teamName]
);
}
}
}
Мы собираемся получить большой выигрыш в FF, верно?;)