您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Extract player rankings data (name, level, experience) and export to CSV
// ==UserScript== // @name The West Rankings CSV Exporter // @namespace TW-Export-Player-CSV // @version 1.0 // @description Extract player rankings data (name, level, experience) and export to CSV // @author Frozah // @include https://*.the-west.*/game.php* // @grant none // ==/UserScript== (function (fn) { var script = document.createElement('script'); script.setAttribute('type', 'application/javascript'); script.textContent = '(' + fn + ')();'; document.body.appendChild(script); document.body.removeChild(script); })(function () { RankingExporter = { version: '1.0', name: 'Rankings CSV Exporter', author: 'Assistant', preferences: { includeAllPages: true, maxPages: 16 }, // Données collectées playersData: [], currentPage: 1, totalPages: 16, isScrapingInProgress: false, progressBar: null, // Interface utilisateur selectBox: null, // Initialisation du script init: function() { this.createSelectBox(); this.addMenuButton(); }, // Création de la boîte de sélection createSelectBox: function() { var self = this; var listener = function(action) { switch(action) { case 'export_current': self.exportCurrentPage(); break; case 'export_all': self.exportAllPages(); break; case 'stop_scraping': self.stopScraping(); break; } }; this.selectBox = new west.gui.Selectbox() .setWidth(200) .addListener(listener) .addItem('export_current', 'Exporter page actuelle') .addItem('export_all', 'Exporter toutes les pages') .addItem('stop_scraping', 'Arrêter le scraping'); }, // Ajout du bouton dans le menu addMenuButton: function() { var self = this; // Création d'un bouton simple (carré coloré) var menuButton = $('<div id="RankingExportermenu" class="menulink" title="' + this.name + '" />') .css({ 'background-color': '#8B4513', 'width': '25px', 'height': '25px', 'cursor': 'pointer', 'border': '2px solid #654321', 'margin': '2px' }) .on('mouseenter', function() { $(this).css('background-color', '#A0522D'); }) .on('mouseleave', function() { $(this).css('background-color', '#8B4513'); }) .click(function() { self.toggleSelectbox(); }); var div = $('<div class="ui_menucontainer" />') .append(menuButton) .append('<div class="menucontainer_bottom" />'); $('#ui_menubar').append(div); }, // Affichage/masquage de la boîte de sélection toggleSelectbox: function() { var pos = $('div#RankingExportermenu').offset(); pos = { clientX: pos.left, clientY: pos.top }; this.selectBox.show(pos); }, // Extraction des données de la page actuelle extractCurrentPageData: function() { var data = []; var rows = $('.ranking-experience .tbody .tw2gui_scrollpane_clipper_contentpane .row'); rows.each(function(index) { var row = $(this); // Extraire le nom du joueur var playerNameCell = row.find('.exp_playername a'); var playerName = ''; if (playerNameCell.length > 0) { playerName = playerNameCell.text().trim(); } else { // Si pas de lien, prendre le texte direct playerName = row.find('.exp_playername').text().trim(); } // Extraire le niveau var level = row.find('.exp_level').text().trim(); // Extraire l'expérience var experience = row.find('.exp_exp').text().trim(); // Extraire le rang var rank = row.find('.exp_rank').text().trim(); if (playerName && level && experience && rank) { data.push({ rank: rank, name: playerName, level: level, experience: experience }); } }); return data; }, // Export de la page actuelle exportCurrentPage: function() { var data = this.extractCurrentPageData(); if (data.length === 0) { new UserMessage('Aucune donnée trouvée sur cette page', UserMessage.TYPE_ERROR).show(); return; } this.generateCSV(data, 'rankings_current_page.csv'); new UserMessage('Export de la page actuelle terminé (' + data.length + ' joueurs)', UserMessage.TYPE_SUCCESS).show(); }, // Export de toutes les pages exportAllPages: function() { if (this.isScrapingInProgress) { new UserMessage('Scraping déjà en cours...', UserMessage.TYPE_ERROR).show(); return; } this.isScrapingInProgress = true; this.playersData = []; this.currentPage = 1; // Déterminer le nombre total de pages this.getTotalPages(); new UserMessage('Début du scraping de ' + this.totalPages + ' pages...', UserMessage.TYPE_HINT).show(); // Créer une barre de progression this.createProgressDialog(); // Commencer le scraping this.scrapePage(1); }, // Déterminer le nombre total de pages getTotalPages: function() { // Méthode 1: Chercher dans la pagination var paginationText = $('.rl_pagebar_ranking .maxpages').text(); if (paginationText) { var match = paginationText.match(/\/\s*(\d+)/); if (match) { this.totalPages = parseInt(match[1]); return; } } // Méthode 2: Compter les liens de pagination var pageLinks = $('.rl_pagebar_ranking .pagebar_page'); if (pageLinks.length > 0) { var lastPage = 1; pageLinks.each(function() { var pageNum = parseInt($(this).text()); if (!isNaN(pageNum) && pageNum > lastPage) { lastPage = pageNum; } }); this.totalPages = lastPage; return; } // Par défaut, utiliser 16 pages this.totalPages = 16; }, // Créer la boîte de dialogue de progression createProgressDialog: function() { var self = this; var content = $('<div><p>Scraping en cours...</p></div>'); this.progressBar = new west.gui.Progressbar(0, this.totalPages); content.append(this.progressBar.getMainDiv()); this.progressDialog = new west.gui.Dialog("Export en cours", content); this.progressDialog.addButton("Annuler", function() { self.stopScraping(); self.progressDialog.hide(); }); this.progressDialog.show(); }, // Scraping d'une page spécifique scrapePage: function(pageNumber) { var self = this; if (!this.isScrapingInProgress || pageNumber > this.totalPages) { this.finalizeScraping(); return; } // Mettre à jour la barre de progression if (this.progressBar) { this.progressBar.setValue(pageNumber - 1); } new UserMessage('Scraping de la page ' + pageNumber + '/' + this.totalPages + '...', UserMessage.TYPE_HINT).show(); // Aller à la page this.goToPage(pageNumber, function() { setTimeout(function() { // Attendre que la page soit complètement chargée self.waitForPageLoad(function() { var pageData = self.extractCurrentPageData(); self.playersData = self.playersData.concat(pageData); console.log('Page ' + pageNumber + ' scrapée: ' + pageData.length + ' joueurs'); // Passer à la page suivante setTimeout(function() { self.scrapePage(pageNumber + 1); }, 1500); // Délai entre les pages augmenté }); }, 1000); // Délai initial pour laisser la page se charger }); }, // Attendre que la page soit chargée waitForPageLoad: function(callback) { var self = this; var attempts = 0; var maxAttempts = 10; var checkLoad = function() { attempts++; var rows = $('.ranking-experience .tbody .tw2gui_scrollpane_clipper_contentpane .row'); if (rows.length > 0 || attempts >= maxAttempts) { callback(); } else { setTimeout(checkLoad, 500); } }; checkLoad(); }, // Navigation vers une page spécifique (améliorée) goToPage: function(pageNumber, callback) { var self = this; try { // Méthode 1: Utiliser le champ de saisie de page var pageInput = $('.rl_pagebar_ranking .tw2gui_textfield input[type="text"]'); if (pageInput.length > 0) { pageInput.val(pageNumber); // Déclencher les événements pour valider la saisie pageInput.trigger('input'); pageInput.trigger('change'); // Simuler la touche Entrée var enterEvent = jQuery.Event('keypress'); enterEvent.which = 13; // Code de la touche Entrée enterEvent.keyCode = 13; pageInput.trigger(enterEvent); setTimeout(function() { if (callback) callback(); }, 800); return; } // Méthode 2: Utiliser Ajax directement (inspirée du second script) if (typeof Ajax !== 'undefined' && Ajax.remoteCall) { Ajax.remoteCall("ranking", "get_ranking_page", { page: pageNumber, type: "experience" }, function(response) { // Attendre que la page soit mise à jour setTimeout(function() { if (callback) callback(); }, 500); }); return; } // Méthode 3: Cliquer sur le lien de pagination var pageLink = $('.rl_pagebar_ranking .pagebar_page').filter(function() { return $(this).text() == pageNumber; }); if (pageLink.length > 0) { pageLink.click(); setTimeout(function() { if (callback) callback(); }, 800); return; } // Si aucune méthode ne fonctionne, continuer quand même console.log('Impossible de naviguer vers la page ' + pageNumber); if (callback) callback(); } catch (e) { console.error('Erreur lors de la navigation vers la page ' + pageNumber + ':', e); if (callback) callback(); } }, // Finalisation du scraping finalizeScraping: function() { this.isScrapingInProgress = false; // Fermer la boîte de dialogue de progression if (this.progressDialog) { this.progressDialog.hide(); } if (this.playersData.length === 0) { new UserMessage('Aucune donnée collectée', UserMessage.TYPE_ERROR).show(); return; } // Tri par rang this.playersData.sort(function(a, b) { return parseInt(a.rank) - parseInt(b.rank); }); // Supprimer les doublons (au cas où) var uniqueData = []; var seenRanks = {}; for (var i = 0; i < this.playersData.length; i++) { var player = this.playersData[i]; if (!seenRanks[player.rank]) { uniqueData.push(player); seenRanks[player.rank] = true; } } this.generateCSV(uniqueData, 'rankings_all_pages.csv'); new UserMessage('Export terminé ! ' + uniqueData.length + ' joueurs exportés', UserMessage.TYPE_SUCCESS).show(); }, // Arrêt du scraping stopScraping: function() { this.isScrapingInProgress = false; if (this.progressDialog) { this.progressDialog.hide(); } new UserMessage('Scraping arrêté', UserMessage.TYPE_ERROR).show(); }, // Génération du fichier CSV generateCSV: function(data, filename) { if (data.length === 0) { return; } // En-têtes CSV var csv = 'Rang,Nom du joueur,Niveau,Expérience\n'; // Données data.forEach(function(player) { // Échapper les guillemets et virgules var name = '"' + player.name.replace(/"/g, '""') + '"'; var experience = '"' + player.experience.replace(/"/g, '""') + '"'; csv += player.rank + ',' + name + ',' + player.level + ',' + experience + '\n'; }); // Téléchargement du fichier this.downloadCSV(csv, filename); }, // Téléchargement du fichier CSV downloadCSV: function(csvContent, filename) { var blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); var link = document.createElement('a'); if (link.download !== undefined) { var url = URL.createObjectURL(blob); link.setAttribute('href', url); link.setAttribute('download', filename); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); } }, // Vérification si on est sur la page des classements isOnRankingsPage: function() { return $('.ranking-experience').length > 0; } }; // Initialisation une fois le document prêt $(document).ready(function() { try { // Attendre que les objets du jeu soient disponibles var initInterval = setInterval(function() { if (typeof west !== 'undefined' && typeof west.gui !== 'undefined' && typeof west.gui.Selectbox !== 'undefined' && typeof UserMessage !== 'undefined') { clearInterval(initInterval); RankingExporter.init(); } }, 1000); } catch (e) { console.log('Erreur lors de l\'initialisation du script Rankings Exporter:', e); } }); // Debug : afficher le nom du script dans la console console.log('Script Rankings CSV Exporter v' + RankingExporter.version + ' chargé'); });