[YouTube] Fix playlist continuations extraction

This commit is contained in:
XiangRongLin 2020-11-17 21:04:53 +01:00
parent 6701b0fe71
commit 8347e14952
2 changed files with 28 additions and 13 deletions

View File

@ -190,9 +190,10 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
return new InfoItemsPage<>(collector, null); return new InfoItemsPage<>(collector, null);
} else if (contents.getObject(0).has("playlistVideoListRenderer")) { } else if (contents.getObject(0).has("playlistVideoListRenderer")) {
final JsonObject videos = contents.getObject(0).getObject("playlistVideoListRenderer"); final JsonObject videos = contents.getObject(0).getObject("playlistVideoListRenderer");
collectStreamsFrom(collector, videos.getArray("contents")); final JsonArray videosArray = videos.getArray("contents");
collectStreamsFrom(collector, videosArray);
nextPage = getNextPageFrom(videos.getArray("continuations")); nextPage = getNextPageFrom(videosArray);
} }
return new InfoItemsPage<>(collector, nextPage); return new InfoItemsPage<>(collector, nextPage);
@ -207,24 +208,29 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
final JsonArray ajaxJson = getJsonResponse(page.getUrl(), getExtractorLocalization()); final JsonArray ajaxJson = getJsonResponse(page.getUrl(), getExtractorLocalization());
final JsonObject sectionListContinuation = ajaxJson.getObject(1).getObject("response") final JsonArray continuation = ajaxJson.getObject(1)
.getObject("continuationContents").getObject("playlistVideoListContinuation"); .getObject("response")
.getArray("onResponseReceivedActions")
.getObject(0)
.getObject("appendContinuationItemsAction")
.getArray("continuationItems");
collectStreamsFrom(collector, sectionListContinuation.getArray("contents")); collectStreamsFrom(collector, continuation);
return new InfoItemsPage<>(collector, getNextPageFrom(sectionListContinuation.getArray("continuations"))); return new InfoItemsPage<>(collector, getNextPageFrom(continuation));
} }
private Page getNextPageFrom(final JsonArray continuations) { private Page getNextPageFrom(final JsonArray contents) {
if (isNullOrEmpty(continuations)) { if (isNullOrEmpty(contents)) {
return null; return null;
} }
final JsonObject nextContinuationData = continuations.getObject(0).getObject("nextContinuationData"); final String continuation = contents.getObject(contents.size() - 1)
final String continuation = nextContinuationData.getString("continuation"); .getObject("continuationItemRenderer")
final String clickTrackingParams = nextContinuationData.getString("clickTrackingParams"); .getObject("continuationEndpoint")
return new Page("https://www.youtube.com/browse_ajax?ctoken=" + continuation + "&continuation=" + continuation .getObject("continuationCommand")
+ "&itct=" + clickTrackingParams); .getString("token");
return new Page("https://www.youtube.com/browse_ajax?continuation=" + continuation);
} }
private void collectStreamsFrom(final StreamInfoItemsCollector collector, final JsonArray videos) { private void collectStreamsFrom(final StreamInfoItemsCollector collector, final JsonArray videos) {

View File

@ -3,6 +3,9 @@ package org.schabi.newpipe.extractor.services.youtube;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.DownloaderTestImpl;
import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
@ -11,6 +14,10 @@ import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
import org.schabi.newpipe.extractor.services.BasePlaylistExtractorTest; import org.schabi.newpipe.extractor.services.BasePlaylistExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.YoutubePlaylistExtractorTest.HugePlaylist;
import org.schabi.newpipe.extractor.services.youtube.YoutubePlaylistExtractorTest.LearningPlaylist;
import org.schabi.newpipe.extractor.services.youtube.YoutubePlaylistExtractorTest.NotAvailable;
import org.schabi.newpipe.extractor.services.youtube.YoutubePlaylistExtractorTest.TimelessPopHits;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubePlaylistExtractor; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubePlaylistExtractor;
import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem;
@ -23,6 +30,8 @@ import static org.schabi.newpipe.extractor.services.DefaultTests.*;
/** /**
* Test for {@link YoutubePlaylistExtractor} * Test for {@link YoutubePlaylistExtractor}
*/ */
@RunWith(Suite.class)
@SuiteClasses({NotAvailable.class, TimelessPopHits.class, HugePlaylist.class, LearningPlaylist.class})
public class YoutubePlaylistExtractorTest { public class YoutubePlaylistExtractorTest {
public static class NotAvailable { public static class NotAvailable {