Tout aussi frustré par le manque d'options de filtrage / tri décentes dans Google Play, et inspiré par votre suggestion qu'un script Greasemonkey pourrait résoudre le problème, j'ai décidé d'en écrire un, que j'ai téléchargé sur https://greasyfork.org/en/ scripts / 24667-google-play-review-rating-filter . Il ajoute cinq cases à cocher aux pages d'application sur play.google.com qui vous permettent de filtrer les avis avec des notes spécifiques. Je l'ai testé avec Greasemonkey et Unified Script Injector dans Firefox et Tampermonkey dans Chrome.
Plutôt que de reproduire l'intégralité du script ici, je décrirai l'approche adoptée pour ceux qui pourraient être intéressés. TL; DR: Si vous voulez juste la solution, installez le module complémentaire de navigateur approprié et téléchargez le script utilisateur à partir du lien ci-dessus. Notez que si vous souhaitez l'utiliser sur votre appareil Android lui-même, vous devrez probablement utiliser Firefox avec le module complémentaire USI (et également sélectionner Demander un site de bureau dans le menu), car la plupart des autres navigateurs Android ne prennent pas en charge l'add- ons ou scripts utilisateur et Greasemonkey ne fonctionne pas actuellement dans Firefox pour Android - il ne fonctionnera pas dans l'application Google Play.
Lorsque vous parcourez les avis, GP (Google Play) charge des données pour plus d'avis via des requêtes AJAX vers l'URL /store/getreviews
à l'aide de la POST
méthode HTTP . Ainsi, en raccordant ces appels AJAX, il est possible de modifier les données renvoyées à GP.
XMLHttpRequest.prototype.open
peut être remplacé par une fonction qui appellera l'original, mais d'abord, si la demande concerne des données de révision, modifiez l' XMLHttpRequest
objet XHR ( ) afin que le POST
corps de la demande puisse être capturé et la réponse modifiée. Une send
propriété peut être affectée à l'objet XHR en tant que fonction qui stockera les POST
données avant d'appeler l'original. La onreadystatechange
propriété peut être affectée en tant que fonction qui modifiera la réponse avant d'appeler la fonction affectée par GP à cette propriété. Comme GP l'attribuera onreadystatechange
après cela, Object.defineProperty
il devra être utilisé pour redéfinir la propriété afin que la valeur définie par GP soit stockée plutôt que d'être réellement affectée à la propriété interne. Et comme la responseText
propriété est en lecture seule, il Object.defineProperty
faudrait modifier sa valeur.
Les données renvoyées par GP sont au format JSON, mais contiennent au début quelques caractères indésirables qui doivent être fidèlement reproduits dans toutes les données modifiées.
Le code suivant le montre et affichera dans la fenêtre de la console du développeur du navigateur le corps de la demande et les données de réponse (bien qu'il ne les modifie pas réellement):
XMLHttpRequest.prototype.open = (function(open) {
return function(method, url) {
if (
method === 'POST' &&
url &&
url.replace(/^https?:\/\/play\.google\.com/, '').split('?', 1)[0] ===
'/store/getreviews'
) {
var requestBody;
var orgSend = this.send;
var orgOnReadyStateChange = this.onreadystatechange;
this.send = function(data) {
requestBody = data;
return orgSend.apply(this, arguments);
};
this.onreadystatechange = function() {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
var responseText = this.responseText;
var nJunkChars = responseText.indexOf('[');
try {
var jsonData = JSON.parse(
nJunkChars ? responseText.substr(nJunkChars) : responseText
);
// TODO: modify jsonData here
console.log('Request: %o\nResponse: %o', requestBody, jsonData);
Object.defineProperty(this, 'responseText', {
value: responseText.substr(0, nJunkChars) +
JSON.stringify(jsonData),
configurable: true,
enumerable: true
});
} catch (e) {
console && console.log && console.log(e);
}
}
if (orgOnReadyStateChange) {
return orgOnReadyStateChange.apply(this, arguments);
}
};
Object.defineProperty(this, 'onreadystatechange', {
get: function() { return orgOnReadyStateChange; },
set: function(v) { orgOnReadyStateChange = v; },
configurable: true,
enumerable: true
});
}
return open.apply(this, arguments);
};
})(XMLHttpRequest.prototype.open);
Les données renvoyées par GP comprennent un tableau d'un élément qui est un tableau de quatre éléments comme suit:
- La chaîne
"ecr"
;
1
s'il y a plus d'avis, 2
s'il s'agit de la dernière «page» d'avis, 3
si une erreur s'est produite;
- Le HTML contenant la «page» des avis (et toutes les réponses des développeurs) - actuellement 40 avis sont renvoyés par page;
- Numéro de page, correspondant au
pageNum
paramètre dans le corps de la requête POST.
Le code HTML peut être modifié pour supprimer les avis (et toute réponse de développeur associée) avec des notes autres que celles qui vous intéressent. Les avis correspondent au sélecteur div.single-review
et ont un descendant correspondant div.current-rating
à un style en ligne où la propriété CSS width est un pourcentage correspondant à la note ( 20%
pour 1 étoile, 40%
pour 2 étoiles, etc.). Les réponses des développeurs correspondent au sélecteur div.developer-reply
et sont des frères et sœurs immédiatement après l'examen.
L'ajout de cases à cocher dans l'interface utilisateur pour permettre de choisir les étoiles des avis à afficher est assez simple. Cependant, lorsque leurs sélections sont modifiées, les avis doivent être récupérés à nouveau. La modification de l'ordre de tri provoque cela, tout comme la sélection du même ordre de tri qu'auparavant. Donc, pour y parvenir automatiquement, chaque fois qu'une case est modifiée, un click
événement peut être déclenché sur l'élément d'ordre de tri actuellement sélectionné, qui peut être trouvé avec un sélecteur de .id-review-sort-filter .dropdown-child.selected
. Lorsqu'une page d'application sur GP est initialement chargée, la première page d'avis est déjà incluse et n'est pas chargée via AJAX, mais tant que les cases à cocher sont toutes initialement cochées, cela n'a pas d'importance.
Parfois, une page de (40) avis n'en contient pas avec la note souhaitée. Si aucun élément n'existe dans le code HTML renvoyé, GP ne demandera plus de pages. Donc, pour répondre à cela, il serait nécessaire de récupérer des pages supplémentaires de critiques (via la même API AJAX, mais en modifiant le pageNum
paramètre) jusqu'à ce qu'il y ait des critiques à retourner. Et pour les pages suivantes, le pageNum
paramètre aurait besoin d'être traduit pour en tenir compte.
Lorsque l'ordre de tri sélectionné est «Note», il peut y avoir plusieurs pages d'avis 5 étoiles avant tout avec une note souhaitée. La récupération et la suppression répétées de pages et de pages d'avis seraient inefficaces (et pourraient déclencher un blocage IP temporaire par Google). Dans ce cas, lorsque le reviewSortOrder
paramètre est 1
, une recherche binaire peut être employée pour trouver beaucoup plus rapidement la page suivante avec des commentaires à retourner. Un élément de page correspondant au sélecteur span.reviews-num
peut être inspecté pour trouver le nombre total d'avis et ainsi déterminer un numéro de page supérieur lié. Cependant, comme il s'avère actuellement, les demandes de pages au-delà de la page 111 reçoivent une réponse HTTP 400.