Sama-sama frustrasi dengan kurangnya opsi pemfilteran / penyortiran yang layak di Google Play, dan terinspirasi oleh saran Anda bahwa skrip Greasemonkey dapat menyelesaikan masalah, saya memutuskan untuk menulis satu, yang telah saya unggah ke https://greasyfork.org/en/ script / 24667-google-play-review-rating-filter . Itu menambahkan lima kotak centang ke halaman aplikasi di play.google.com yang memungkinkan Anda untuk menyaring ulasan dengan peringkat bintang tertentu. Saya sudah mengujinya dengan Greasemonkey dan Unified Script Injector di Firefox, dan Tampermonkey di Chrome.
Daripada mereproduksi seluruh skrip di sini, saya akan menjelaskan pendekatan yang dilakukan untuk mereka yang mungkin tertarik. TL; DR: Jika Anda hanya menginginkan solusinya, instal add-on browser yang sesuai dan unduh skrip pengguna dari tautan di atas. Perhatikan bahwa jika Anda ingin menggunakannya di perangkat Android Anda sendiri, Anda mungkin perlu menggunakan Firefox dengan add-on USI (dan juga pilih Request Desktop Site dari menu), karena sebagian besar browser Android lainnya tidak mendukung add-on. ons atau skrip pengguna dan Greasemonkey saat ini tidak berfungsi di Firefox untuk Android - itu tidak akan berfungsi di aplikasi Google Play.
Saat Anda membolak-balik ulasan, GP (Google Play) memuat data untuk lebih banyak ulasan melalui permintaan AJAX ke URL /store/getreviews
menggunakan POST
metode HTTP . Jadi dengan mengaitkan panggilan AJAX ini, dimungkinkan untuk memodifikasi data yang dikembalikan ke GP.
XMLHttpRequest.prototype.open
dapat diganti dengan fungsi yang akan memanggil yang asli, tetapi pertama-tama, jika permintaan untuk data ulasan, modifikasi objek XHR ( XMLHttpRequest
) sehingga POST
badan permintaan dapat ditangkap dan responsnya diubah. Sebuah send
properti dapat ditugaskan ke objek XHR sebagai fungsi yang akan menyimpan POST
data sebelum memanggil aslinya. The onreadystatechange
properti dapat ditugaskan sebagai fungsi yang akan memodifikasi respon sebelum memanggil fungsi yang ditetapkan oleh GP untuk properti ini. Karena GP akan menetapkan onreadystatechange
setelah ini, Object.defineProperty
perlu digunakan untuk mendefinisikan kembali properti sehingga nilai set GP disimpan daripada benar-benar ditugaskan ke properti internal. Dan karena responseText
properti hanya baca, Object.defineProperty
akan diperlukan untuk mengubah nilainya.
Data yang dikembalikan oleh GP adalah dalam format JSON, meskipun memiliki beberapa karakter sampah di awal yang harus direproduksi dengan setia dalam setiap data yang dimodifikasi.
Kode berikut menunjukkan ini, dan akan menampilkan ke jendela konsol pengembang browser badan permintaan dan data respons (meskipun tidak benar-benar memodifikasinya):
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);
Data yang dikembalikan oleh GP terdiri dari array dari satu elemen yang merupakan array dari empat elemen sebagai berikut:
- String
"ecr"
;
1
jika ada lebih banyak ulasan, 2
jika ini adalah 'halaman' ulasan terakhir, 3
jika terjadi kesalahan;
- HTML yang berisi 'halaman' ulasan (dan balasan pengembang mana pun) - saat ini 40 ulasan dikembalikan per halaman;
- Nomor halaman, sesuai dengan
pageNum
parameter di badan permintaan POST.
HTML dapat dimodifikasi untuk menghapus ulasan (dan balasan pengembang terkait) dengan peringkat bintang selain yang menarik. Ulasan cocok dengan pemilih div.single-review
dan memiliki keturunan yang cocok div.current-rating
dengan gaya inline di mana properti lebar CSS adalah persentase yang sesuai dengan peringkat ( 20%
untuk 1 bintang, 40%
untuk 2 bintang, dll). Balasan pengembang cocok dengan pemilih div.developer-reply
dan saudara kandung segera setelah ulasan.
Menambahkan kotak centang ke UI untuk memungkinkan memilih peringkat bintang ulasan yang akan ditampilkan cukup mudah. Namun, ketika pilihan mereka diubah, ulasan harus diambil lagi. Mengubah urutan sortir menyebabkan hal ini terjadi, seperti halnya bahkan memilih urutan sortir yang sama seperti sebelumnya. Jadi untuk mencapai ini secara otomatis, setiap kali kotak centang diubah, click
peristiwa dapat dipicu pada elemen urutan sortir yang saat ini dipilih, yang dapat ditemukan dengan pemilih .id-review-sort-filter .dropdown-child.selected
. Ketika halaman aplikasi pada GP awalnya dimuat, halaman pertama ulasan sudah termasuk dan tidak dimuat melalui AJAX, tetapi selama semua kotak centang pada awalnya diperiksa, itu tidak masalah.
Kadang-kadang halaman (40) ulasan tidak berisi apa pun dengan peringkat yang diinginkan. Jika tidak ada elemen dalam HTML yang dikembalikan, GP tidak akan meminta halaman lagi. Jadi untuk memenuhi hal ini, perlu mengambil halaman ulasan tambahan (melalui API AJAX yang sama, tetapi memodifikasi pageNum
parameter) sampai ada beberapa ulasan untuk dikembalikan. Dan untuk halaman berikutnya, pageNum
parameter perlu diterjemahkan ke akun untuk ini.
Ketika urutan pengurutan yang dipilih adalah 'Peringkat', mungkin ada banyak halaman ulasan bintang 5 sebelum apa pun dengan peringkat yang diinginkan. Pengambilan berulang-ulang dan membuang halaman dan halaman ulasan akan menjadi tidak efisien (dan dapat memicu blok IP sementara oleh Google). Dalam hal ini, ketika reviewSortOrder
parameternya adalah 1
, pencarian biner dapat digunakan untuk menemukan halaman berikutnya dengan ulasan yang lebih cepat untuk dikembalikan. Elemen halaman yang cocok dengan pemilih span.reviews-num
dapat diperiksa untuk menemukan jumlah total ulasan dan dengan demikian menentukan jumlah halaman yang terikat. Meskipun, saat ini ternyata, permintaan untuk halaman di luar halaman 111 menerima respons HTTP 400.