extractors: Add support for reelItemRenderer
This commit is contained in:
parent
f267394bbe
commit
46a63e6150
|
@ -17,6 +17,7 @@ private ITEM_PARSERS = {
|
||||||
Parsers::PlaylistRendererParser,
|
Parsers::PlaylistRendererParser,
|
||||||
Parsers::CategoryRendererParser,
|
Parsers::CategoryRendererParser,
|
||||||
Parsers::RichItemRendererParser,
|
Parsers::RichItemRendererParser,
|
||||||
|
Parsers::ReelItemRendererParser,
|
||||||
}
|
}
|
||||||
|
|
||||||
record AuthorFallback, name : String, id : String
|
record AuthorFallback, name : String, id : String
|
||||||
|
@ -369,7 +370,7 @@ private module Parsers
|
||||||
end
|
end
|
||||||
|
|
||||||
# Parses an InnerTube richItemRenderer into a SearchVideo.
|
# Parses an InnerTube richItemRenderer into a SearchVideo.
|
||||||
# Returns nil when the given object isn't a shelfRenderer
|
# Returns nil when the given object isn't a RichItemRenderer
|
||||||
#
|
#
|
||||||
# A richItemRenderer seems to be a simple wrapper for a videoRenderer, used
|
# A richItemRenderer seems to be a simple wrapper for a videoRenderer, used
|
||||||
# by the result page for hashtags. It is located inside a continuationItems
|
# by the result page for hashtags. It is located inside a continuationItems
|
||||||
|
@ -390,6 +391,90 @@ private module Parsers
|
||||||
return {{@type.name}}
|
return {{@type.name}}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Parses an InnerTube reelItemRenderer into a SearchVideo.
|
||||||
|
# Returns nil when the given object isn't a reelItemRenderer
|
||||||
|
#
|
||||||
|
# reelItemRenderer items are used in the new (2022) channel layout,
|
||||||
|
# in the "shorts" tab.
|
||||||
|
#
|
||||||
|
module ReelItemRendererParser
|
||||||
|
def self.process(item : JSON::Any, author_fallback : AuthorFallback)
|
||||||
|
if item_contents = item["reelItemRenderer"]?
|
||||||
|
return self.parse(item_contents, author_fallback)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private def self.parse(item_contents, author_fallback)
|
||||||
|
video_id = item_contents["videoId"].as_s
|
||||||
|
|
||||||
|
video_details_container = item_contents.dig(
|
||||||
|
"navigationEndpoint", "reelWatchEndpoint",
|
||||||
|
"overlay", "reelPlayerOverlayRenderer",
|
||||||
|
"reelPlayerHeaderSupportedRenderers",
|
||||||
|
"reelPlayerHeaderRenderer"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Author infos
|
||||||
|
|
||||||
|
author = video_details_container
|
||||||
|
.dig?("channelTitleText", "runs", 0, "text")
|
||||||
|
.try &.as_s || author_fallback.name
|
||||||
|
|
||||||
|
ucid = video_details_container
|
||||||
|
.dig?("channelNavigationEndpoint", "browseEndpoint", "browseId")
|
||||||
|
.try &.as_s || author_fallback.id
|
||||||
|
|
||||||
|
# Title & publication date
|
||||||
|
|
||||||
|
title = video_details_container.dig?("reelTitleText")
|
||||||
|
.try { |t| extract_text(t) } || ""
|
||||||
|
|
||||||
|
published = video_details_container
|
||||||
|
.dig?("timestampText", "simpleText")
|
||||||
|
.try { |t| decode_date(t.as_s) } || Time.utc
|
||||||
|
|
||||||
|
# View count
|
||||||
|
|
||||||
|
view_count_text = video_details_container.dig?("viewCountText", "simpleText")
|
||||||
|
view_count_text ||= video_details_container
|
||||||
|
.dig?("viewCountText", "accessibility", "accessibilityData", "label")
|
||||||
|
|
||||||
|
view_count = view_count_text.try &.as_s.gsub(/\D+/, "").to_i64? || 0_i64
|
||||||
|
|
||||||
|
# Duration
|
||||||
|
|
||||||
|
a11y_data = item_contents
|
||||||
|
.dig?("accessibility", "accessibilityData", "label")
|
||||||
|
.try &.as_s || ""
|
||||||
|
|
||||||
|
regex_match = /- (?<min>\d+ minutes? )?(?<sec>\d+ seconds?)+ -/.match(a11y_data)
|
||||||
|
|
||||||
|
minutes = regex_match.try &.["min"].to_i(strict: false) || 0
|
||||||
|
seconds = regex_match.try &.["sec"].to_i(strict: false) || 0
|
||||||
|
|
||||||
|
duration = (minutes*60 + seconds)
|
||||||
|
|
||||||
|
SearchVideo.new({
|
||||||
|
title: title,
|
||||||
|
id: video_id,
|
||||||
|
author: author,
|
||||||
|
ucid: ucid,
|
||||||
|
published: published,
|
||||||
|
views: view_count,
|
||||||
|
description_html: "",
|
||||||
|
length_seconds: duration,
|
||||||
|
live_now: false,
|
||||||
|
premium: false,
|
||||||
|
premiere_timestamp: Time.unix(0),
|
||||||
|
author_verified: false,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.parser_name
|
||||||
|
return {{@type.name}}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# The following are the extractors for extracting an array of items from
|
# The following are the extractors for extracting an array of items from
|
||||||
|
|
Loading…
Reference in New Issue