mirror of
https://github.com/TeamNewPipe/NewPipeExtractor.git
synced 2025-04-29 08:20:34 +05:30
Merge pull request #926 from AudricV/fix-yt-like-count-extraction
[YouTube] Fix extraction of like count with the new data model
This commit is contained in:
commit
884da40f65
@ -417,28 +417,88 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
|||||||
@Override
|
@Override
|
||||||
public long getLikeCount() throws ParsingException {
|
public long getLikeCount() throws ParsingException {
|
||||||
assertPageFetched();
|
assertPageFetched();
|
||||||
String likesString = "";
|
|
||||||
try {
|
|
||||||
likesString = getVideoPrimaryInfoRenderer()
|
|
||||||
.getObject("videoActions")
|
|
||||||
.getObject("menuRenderer")
|
|
||||||
.getArray("topLevelButtons")
|
|
||||||
.getObject(0)
|
|
||||||
.getObject("toggleButtonRenderer")
|
|
||||||
.getObject("defaultText")
|
|
||||||
.getObject("accessibility")
|
|
||||||
.getObject("accessibilityData")
|
|
||||||
.getString("label");
|
|
||||||
|
|
||||||
if (likesString == null) {
|
// If ratings are not allowed, there is no like count available
|
||||||
// If this kicks in our button has no content and therefore ratings must be disabled
|
if (!playerResponse.getObject("videoDetails").getBoolean("allowRatings")) {
|
||||||
if (playerResponse.getObject("videoDetails").getBoolean("allowRatings")) {
|
|
||||||
throw new ParsingException(
|
|
||||||
"Ratings are enabled even though the like button is missing");
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String likesString = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
final JsonArray topLevelButtons = getVideoPrimaryInfoRenderer()
|
||||||
|
.getObject("videoActions")
|
||||||
|
.getObject("menuRenderer")
|
||||||
|
.getArray("topLevelButtons");
|
||||||
|
|
||||||
|
// Try first with the new video actions buttons data structure
|
||||||
|
JsonObject likeToggleButtonRenderer = topLevelButtons.stream()
|
||||||
|
.filter(JsonObject.class::isInstance)
|
||||||
|
.map(JsonObject.class::cast)
|
||||||
|
.map(button -> button.getObject("segmentedLikeDislikeButtonRenderer")
|
||||||
|
.getObject("likeButton")
|
||||||
|
.getObject("toggleButtonRenderer"))
|
||||||
|
.filter(toggleButtonRenderer -> !isNullOrEmpty(toggleButtonRenderer))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
// Use the old video actions buttons data structure if the new one isn't returned
|
||||||
|
if (likeToggleButtonRenderer == null) {
|
||||||
|
/*
|
||||||
|
In the old video actions buttons data structure, there are 3 ways to detect whether
|
||||||
|
a button is the like button, using its toggleButtonRenderer:
|
||||||
|
- checking whether toggleButtonRenderer.targetId is equal to watch-like;
|
||||||
|
- checking whether toggleButtonRenderer.defaultIcon.iconType is equal to LIKE;
|
||||||
|
- checking whether
|
||||||
|
toggleButtonRenderer.toggleButtonSupportedData.toggleButtonIdData.id
|
||||||
|
is equal to TOGGLE_BUTTON_ID_TYPE_LIKE.
|
||||||
|
*/
|
||||||
|
likeToggleButtonRenderer = topLevelButtons.stream()
|
||||||
|
.filter(JsonObject.class::isInstance)
|
||||||
|
.map(JsonObject.class::cast)
|
||||||
|
.map(topLevelButton -> topLevelButton.getObject("toggleButtonRenderer"))
|
||||||
|
.filter(toggleButtonRenderer -> toggleButtonRenderer.getString("targetId")
|
||||||
|
.equalsIgnoreCase("watch-like")
|
||||||
|
|| toggleButtonRenderer.getObject("defaultIcon")
|
||||||
|
.getString("iconType")
|
||||||
|
.equalsIgnoreCase("LIKE")
|
||||||
|
|| toggleButtonRenderer.getObject("toggleButtonSupportedData")
|
||||||
|
.getObject("toggleButtonIdData")
|
||||||
|
.getString("id")
|
||||||
|
.equalsIgnoreCase("TOGGLE_BUTTON_ID_TYPE_LIKE"))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new ParsingException(
|
||||||
|
"The like button is missing even though ratings are enabled"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use one of the accessibility strings available (this one has the same path as the
|
||||||
|
// one used for comments' like count extraction)
|
||||||
|
likesString = likeToggleButtonRenderer.getObject("accessibilityData")
|
||||||
|
.getObject("accessibilityData")
|
||||||
|
.getString("label");
|
||||||
|
|
||||||
|
// Use the other accessibility string available which contains the exact like count
|
||||||
|
if (likesString == null) {
|
||||||
|
likesString = likeToggleButtonRenderer.getObject("accessibility")
|
||||||
|
.getString("label");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last method: use the defaultText's accessibility data, which contains the exact like
|
||||||
|
// count too, except when it is equal to 0, where a localized string is returned instead
|
||||||
|
if (likesString == null) {
|
||||||
|
likesString = likeToggleButtonRenderer.getObject("defaultText")
|
||||||
|
.getObject("accessibility")
|
||||||
|
.getObject("accessibilityData")
|
||||||
|
.getString("label");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If ratings are allowed and the likes string is null, it means that we couldn't
|
||||||
|
// extract the (real) like count from accessibility data
|
||||||
|
if (likesString == null) {
|
||||||
|
throw new ParsingException("Could not get like count from accessibility data");
|
||||||
|
}
|
||||||
|
|
||||||
|
// This check only works with English localizations!
|
||||||
if (likesString.toLowerCase().contains("no likes")) {
|
if (likesString.toLowerCase().contains("no likes")) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -448,11 +508,8 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
|||||||
throw new ParsingException("Could not parse \"" + likesString + "\" as an Integer",
|
throw new ParsingException("Could not parse \"" + likesString + "\" as an Integer",
|
||||||
nfe);
|
nfe);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
if (getAgeLimit() == NO_AGE_LIMIT) {
|
|
||||||
throw new ParsingException("Could not get like count", e);
|
throw new ParsingException("Could not get like count", e);
|
||||||
}
|
}
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
Loading…
x
Reference in New Issue
Block a user