Thất vọng không kém vì thiếu các tùy chọn lọc / sắp xếp hợp lý trong Google Play và được truyền cảm hứng từ đề xuất của bạn rằng tập lệnh Greasemonkey có thể giải quyết vấn đề, tôi quyết định viết một cái mà tôi đã tải lên https://greasyfork.org/en/ scripts / 24667-google-play-review-rating-filter . Nó thêm năm hộp kiểm vào các trang ứng dụng trên play.google.com cho phép bạn lọc các đánh giá với xếp hạng sao cụ thể. Tôi đã thử nghiệm nó với Greasemonkey và Unified Script In phun trong Firefox và Tampermonkey trong Chrome.
Thay vì tái tạo toàn bộ kịch bản ở đây, tôi sẽ mô tả cách tiếp cận được thực hiện cho những người có thể quan tâm. TL; DR: Nếu bạn chỉ muốn giải pháp, hãy cài đặt bổ trợ trình duyệt phù hợp và tải xuống tập lệnh người dùng từ liên kết ở trên. Lưu ý rằng nếu bạn muốn sử dụng nó trên chính thiết bị Android của mình, có thể bạn sẽ cần sử dụng Firefox với tiện ích bổ sung USI (và cũng chọn Request Desktop Site từ menu), vì hầu hết các trình duyệt Android khác không hỗ trợ add- tiện ích hoặc tập lệnh người dùng và Greasemonkey hiện không hoạt động trong Firefox cho Android - nó sẽ không hoạt động trong ứng dụng Google Play.
Khi bạn lướt qua các bài đánh giá, GP (Google Play) tải dữ liệu cho nhiều đánh giá hơn thông qua các yêu cầu AJAX đến URL /store/getreviews
bằng POST
phương thức HTTP . Vì vậy, bằng cách nối các cuộc gọi AJAX này, có thể sửa đổi dữ liệu được trả về GP.
XMLHttpRequest.prototype.open
có thể được thay thế bằng một hàm sẽ gọi bản gốc, nhưng trước tiên, nếu yêu cầu là để xem lại dữ liệu, hãy sửa đổi XMLHttpRequest
đối tượng XHR ( ) để POST
có thể bắt được phần thân yêu cầu và phản hồi được sửa đổi. Một thuộc send
tính có thể được gán cho đối tượng XHR là một hàm sẽ lưu trữ POST
dữ liệu trước khi gọi bản gốc. Các onreadystatechange
bất động sản có thể được gán như một chức năng mà sẽ thay đổi câu trả lời trước khi gọi hàm bằng GP được gán vào thuộc tính này. Vì GP sẽ gán onreadystatechange
sau này, Object.defineProperty
nên sẽ được sử dụng để xác định lại thuộc tính để các giá trị GP được lưu trữ thay vì thực sự được gán cho thuộc tính bên trong. Và vì responseText
tài sản là chỉ đọc, Object.defineProperty
sẽ cần thiết để thay đổi giá trị của nó.
Dữ liệu được trả về bởi GP ở định dạng JSON, mặc dù có một vài ký tự rác khi bắt đầu được sao chép một cách trung thực trong bất kỳ dữ liệu sửa đổi nào.
Đoạn mã sau minh họa điều này và sẽ xuất ra cửa sổ bảng điều khiển dành cho nhà phát triển của trình duyệt, phần thân yêu cầu và dữ liệu phản hồi (mặc dù không thực sự sửa đổi nó):
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);
Dữ liệu được trả về bởi GP bao gồm một mảng gồm một phần tử là một mảng gồm bốn phần tử như sau:
- Chuỗi
"ecr"
;
1
nếu có nhiều đánh giá, 2
nếu đây là 'trang' đánh giá cuối cùng, 3
nếu xảy ra lỗi;
- HTML chứa 'trang' đánh giá (và bất kỳ câu trả lời nào của nhà phát triển) - hiện có 40 đánh giá được trả về mỗi trang;
- Số trang, tương ứng với
pageNum
tham số trong thân yêu cầu POST.
HTML có thể được sửa đổi để xóa các đánh giá (và bất kỳ câu trả lời nào của nhà phát triển được liên kết) với xếp hạng sao khác với các đánh giá quan tâm. Các đánh giá khớp với bộ chọn div.single-review
và có kết quả trùng khớp div.current-rating
với kiểu nội tuyến trong đó thuộc tính chiều rộng CSS là tỷ lệ phần trăm tương ứng với xếp hạng ( 20%
cho 1 sao, 40%
cho 2 sao, v.v.). Trả lời của nhà phát triển phù hợp với bộ chọn div.developer-reply
và là anh chị em ngay sau khi xem xét.
Việc thêm các hộp kiểm vào giao diện người dùng để cho phép chọn xếp hạng sao đánh giá để hiển thị khá đơn giản. Tuy nhiên, khi lựa chọn của họ được thay đổi, các đánh giá cần phải được tìm nạp lại từ đầu. Thay đổi thứ tự sắp xếp khiến điều này xảy ra, thậm chí còn chọn thứ tự sắp xếp giống như trước đây. Vì vậy, để đạt được điều này một cách tự động, bất cứ khi nào một hộp kiểm được thay đổi, một click
sự kiện có thể được kích hoạt trên phần tử thứ tự sắp xếp hiện được chọn, có thể được tìm thấy với một bộ chọn .id-review-sort-filter .dropdown-child.selected
. Khi một trang ứng dụng trên GP ban đầu được tải, trang đánh giá đầu tiên đã được đưa vào và không được tải qua AJAX, nhưng miễn là các hộp kiểm đều được kiểm tra ban đầu, điều đó không thành vấn đề.
Đôi khi một trang của (40) đánh giá sẽ không chứa bất kỳ đánh giá mong muốn nào. Nếu không có phần tử nào tồn tại trong HTML được trả về, GP sẽ không yêu cầu thêm trang nào. Vì vậy, để phục vụ cho việc này, cần phải tìm nạp thêm các trang đánh giá (thông qua cùng AJAX API, nhưng sửa đổi pageNum
tham số) cho đến khi có một số đánh giá để trả về. Và đối với các trang tiếp theo, pageNum
tham số sẽ cần dịch sang tài khoản này.
Khi thứ tự sắp xếp được chọn là 'Xếp hạng', có thể có nhiều trang đánh giá 5 sao trước bất kỳ với xếp hạng mong muốn. Liên tục tìm nạp và loại bỏ các trang và trang đánh giá sẽ không hiệu quả (và có thể kích hoạt một khối IP tạm thời của Google). Trong trường hợp này, khi reviewSortOrder
tham số là 1
, một tìm kiếm nhị phân có thể được sử dụng để nhanh chóng tìm thấy trang tiếp theo với các đánh giá để trả về. Một yếu tố trang phù hợp với bộ chọn span.reviews-num
có thể được kiểm tra để tìm ra tổng số đánh giá và do đó xác định số trang trên bị ràng buộc. Mặc dù, như hiện tại, các yêu cầu cho các trang ngoài trang 111 nhận được phản hồi HTTP 400.