mirror of
https://github.com/TeamNewPipe/NewPipeExtractor.git
synced 2025-04-29 00:10:35 +05:30
Merge pull request #311 from B0pol/fixSearchSuggestion
Search: add isCorrectedSearch() and fix YoutubeSearchExtractor#getSea…
This commit is contained in:
commit
baf5dd3e8f
@ -25,6 +25,16 @@ public abstract class SearchExtractor extends ListExtractor<InfoItem> {
|
|||||||
return getLinkHandler().getSearchString();
|
return getLinkHandler().getSearchString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The search suggestion provided by the service.
|
||||||
|
* <p>
|
||||||
|
* This method also returns the corrected query if
|
||||||
|
* {@link SearchExtractor#isCorrectedSearch()} is true.
|
||||||
|
*
|
||||||
|
* @return a suggestion to another query, the corrected query, or an empty String.
|
||||||
|
* @throws ParsingException
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
public abstract String getSearchSuggestion() throws ParsingException;
|
public abstract String getSearchSuggestion() throws ParsingException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -37,4 +47,14 @@ public abstract class SearchExtractor extends ListExtractor<InfoItem> {
|
|||||||
public String getName() {
|
public String getName() {
|
||||||
return getLinkHandler().getSearchString();
|
return getLinkHandler().getSearchString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell if the search was corrected by the service (if it's not exactly the search you typed).
|
||||||
|
* <p>
|
||||||
|
* Example: on YouTube, if you search for "pewdeipie",
|
||||||
|
* it will give you results for "pewdiepie", then isCorrectedSearch should return true.
|
||||||
|
*
|
||||||
|
* @return whether the results comes from a corrected query or not.
|
||||||
|
*/
|
||||||
|
public abstract boolean isCorrectedSearch() throws ParsingException;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ public class SearchInfo extends ListInfo<InfoItem> {
|
|||||||
|
|
||||||
private String searchString;
|
private String searchString;
|
||||||
private String searchSuggestion;
|
private String searchSuggestion;
|
||||||
|
private boolean isCorrectedSearch;
|
||||||
|
|
||||||
public SearchInfo(int serviceId,
|
public SearchInfo(int serviceId,
|
||||||
SearchQueryHandler qIHandler,
|
SearchQueryHandler qIHandler,
|
||||||
@ -42,7 +43,12 @@ public class SearchInfo extends ListInfo<InfoItem> {
|
|||||||
info.addError(e);
|
info.addError(e);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
info.searchSuggestion = extractor.getSearchSuggestion();
|
info.setSearchSuggestion(extractor.getSearchSuggestion());
|
||||||
|
} catch (Exception e) {
|
||||||
|
info.addError(e);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
info.setIsCorrectedSearch(extractor.isCorrectedSearch());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
info.addError(e);
|
info.addError(e);
|
||||||
}
|
}
|
||||||
@ -64,10 +70,22 @@ public class SearchInfo extends ListInfo<InfoItem> {
|
|||||||
|
|
||||||
// Getter
|
// Getter
|
||||||
public String getSearchString() {
|
public String getSearchString() {
|
||||||
return searchString;
|
return this.searchString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSearchSuggestion() {
|
public String getSearchSuggestion() {
|
||||||
return searchSuggestion;
|
return this.searchSuggestion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCorrectedSearch() {
|
||||||
|
return this.isCorrectedSearch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsCorrectedSearch(boolean isCorrectedSearch) {
|
||||||
|
this.isCorrectedSearch = isCorrectedSearch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchSuggestion(String searchSuggestion) {
|
||||||
|
this.searchSuggestion = searchSuggestion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
|||||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor;
|
import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor;
|
||||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
|
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
|
||||||
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
|
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
|
||||||
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
||||||
@ -42,9 +43,15 @@ public class MediaCCCSearchExtractor extends SearchExtractor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getSearchSuggestion() {
|
public String getSearchSuggestion() {
|
||||||
return null;
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCorrectedSearch() {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -20,6 +20,7 @@ import org.schabi.newpipe.extractor.utils.JsonUtils;
|
|||||||
import org.schabi.newpipe.extractor.utils.Parser;
|
import org.schabi.newpipe.extractor.utils.Parser;
|
||||||
import org.schabi.newpipe.extractor.utils.Parser.RegexException;
|
import org.schabi.newpipe.extractor.utils.Parser.RegexException;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.*;
|
import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.*;
|
||||||
@ -33,9 +34,15 @@ public class PeertubeSearchExtractor extends SearchExtractor {
|
|||||||
super(service, linkHandler);
|
super(service, linkHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getSearchSuggestion() throws ParsingException {
|
public String getSearchSuggestion() throws ParsingException {
|
||||||
return null;
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCorrectedSearch() {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -33,9 +33,15 @@ public class SoundcloudSearchExtractor extends SearchExtractor {
|
|||||||
super(service, linkHandler);
|
super(service, linkHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getSearchSuggestion() {
|
public String getSearchSuggestion() {
|
||||||
return null;
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCorrectedSearch() {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -18,6 +18,7 @@ import org.schabi.newpipe.extractor.localization.TimeAgoParser;
|
|||||||
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
|
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
|
||||||
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
||||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
|
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
|
||||||
|
import org.schabi.newpipe.extractor.utils.JsonUtils;
|
||||||
import org.schabi.newpipe.extractor.utils.Utils;
|
import org.schabi.newpipe.extractor.utils.Utils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -125,15 +126,40 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
|||||||
return super.getUrl();
|
return super.getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getSearchSuggestion() throws ParsingException {
|
public String getSearchSuggestion() throws ParsingException {
|
||||||
final JsonObject didYouMeanRenderer = initialData.getObject("contents").getObject("sectionListRenderer")
|
final JsonObject itemSectionRenderer = initialData.getObject("contents").getObject("sectionListRenderer")
|
||||||
.getArray("contents").getObject(0).getObject("itemSectionRenderer")
|
.getArray("contents").getObject(0).getObject("itemSectionRenderer");
|
||||||
.getArray("contents").getObject(0).getObject("didYouMeanRenderer");
|
if (itemSectionRenderer.isEmpty()) {
|
||||||
if (!didYouMeanRenderer.has("correctedQuery")) {
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return getTextFromObject(didYouMeanRenderer.getObject("correctedQuery"));
|
|
||||||
|
final JsonObject didYouMeanRenderer = itemSectionRenderer.getArray("contents")
|
||||||
|
.getObject(0).getObject("didYouMeanRenderer");
|
||||||
|
final JsonObject showingResultsForRenderer = itemSectionRenderer.getArray("contents").getObject(0)
|
||||||
|
.getObject("showingResultsForRenderer");
|
||||||
|
|
||||||
|
if (!didYouMeanRenderer.isEmpty()) {
|
||||||
|
return getTextFromObject(didYouMeanRenderer.getObject("correctedQuery"));
|
||||||
|
} else if (!showingResultsForRenderer.isEmpty()) {
|
||||||
|
return JsonUtils.getString(showingResultsForRenderer, "correctedQueryEndpoint.searchEndpoint.query");
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCorrectedSearch() {
|
||||||
|
final JsonObject itemSectionRenderer = initialData.getObject("contents").getObject("sectionListRenderer")
|
||||||
|
.getArray("contents").getObject(0).getObject("itemSectionRenderer");
|
||||||
|
if (itemSectionRenderer.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final JsonObject showingResultsForRenderer = itemSectionRenderer.getArray("contents").getObject(0)
|
||||||
|
.getObject("showingResultsForRenderer");
|
||||||
|
return !showingResultsForRenderer.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -2,7 +2,6 @@ package org.schabi.newpipe.extractor.services.youtube.extractors;
|
|||||||
|
|
||||||
import com.grack.nanojson.JsonArray;
|
import com.grack.nanojson.JsonArray;
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.InfoItem;
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
@ -12,10 +11,10 @@ import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
|
|||||||
import org.schabi.newpipe.extractor.localization.TimeAgoParser;
|
import org.schabi.newpipe.extractor.localization.TimeAgoParser;
|
||||||
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
|
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
|
||||||
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.utils.JsonUtils;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonResponse;
|
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonResponse;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
|
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
|
||||||
@ -63,17 +62,35 @@ public class YoutubeSearchExtractor extends SearchExtractor {
|
|||||||
return super.getUrl() + "&gl=" + getExtractorContentCountry().getCountryCode();
|
return super.getUrl() + "&gl=" + getExtractorContentCountry().getCountryCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getSearchSuggestion() throws ParsingException {
|
public String getSearchSuggestion() throws ParsingException {
|
||||||
|
final JsonObject itemSectionRenderer = initialData.getObject("contents")
|
||||||
|
.getObject("twoColumnSearchResultsRenderer").getObject("primaryContents")
|
||||||
|
.getObject("sectionListRenderer").getArray("contents").getObject(0)
|
||||||
|
.getObject("itemSectionRenderer");
|
||||||
|
final JsonObject didYouMeanRenderer = itemSectionRenderer.getArray("contents").getObject(0)
|
||||||
|
.getObject("didYouMeanRenderer");
|
||||||
|
final JsonObject showingResultsForRenderer = itemSectionRenderer.getArray("contents").getObject(0)
|
||||||
|
.getObject("showingResultsForRenderer");
|
||||||
|
|
||||||
|
if (!didYouMeanRenderer.isEmpty()) {
|
||||||
|
return JsonUtils.getString(didYouMeanRenderer, "correctedQueryEndpoint.searchEndpoint.query");
|
||||||
|
} else if (showingResultsForRenderer != null) {
|
||||||
|
return getTextFromObject(showingResultsForRenderer.getObject("correctedQuery"));
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCorrectedSearch() {
|
||||||
final JsonObject showingResultsForRenderer = initialData.getObject("contents")
|
final JsonObject showingResultsForRenderer = initialData.getObject("contents")
|
||||||
.getObject("twoColumnSearchResultsRenderer").getObject("primaryContents")
|
.getObject("twoColumnSearchResultsRenderer").getObject("primaryContents")
|
||||||
.getObject("sectionListRenderer").getArray("contents").getObject(0)
|
.getObject("sectionListRenderer").getArray("contents").getObject(0)
|
||||||
.getObject("itemSectionRenderer").getArray("contents").getObject(0)
|
.getObject("itemSectionRenderer").getArray("contents").getObject(0)
|
||||||
.getObject("showingResultsForRenderer");
|
.getObject("showingResultsForRenderer");
|
||||||
if (!showingResultsForRenderer.has("correctedQuery")) {
|
return !showingResultsForRenderer.isEmpty();
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return getTextFromObject(showingResultsForRenderer.getObject("correctedQuery"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -4,4 +4,5 @@ package org.schabi.newpipe.extractor.services;
|
|||||||
public interface BaseSearchExtractorTest extends BaseListExtractorTest {
|
public interface BaseSearchExtractorTest extends BaseListExtractorTest {
|
||||||
void testSearchString() throws Exception;
|
void testSearchString() throws Exception;
|
||||||
void testSearchSuggestion() throws Exception;
|
void testSearchSuggestion() throws Exception;
|
||||||
|
void testSearchCorrected() throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,10 @@ public abstract class DefaultSearchExtractorTest extends DefaultListExtractorTes
|
|||||||
public abstract String expectedSearchString();
|
public abstract String expectedSearchString();
|
||||||
@Nullable public abstract String expectedSearchSuggestion();
|
@Nullable public abstract String expectedSearchSuggestion();
|
||||||
|
|
||||||
|
public boolean isCorrectedSearch() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Override
|
@Override
|
||||||
public void testSearchString() throws Exception {
|
public void testSearchString() throws Exception {
|
||||||
@ -32,4 +36,9 @@ public abstract class DefaultSearchExtractorTest extends DefaultListExtractorTes
|
|||||||
assertEquals(expectedSearchSuggestion, extractor().getSearchSuggestion());
|
assertEquals(expectedSearchSuggestion, extractor().getSearchSuggestion());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchCorrected() throws Exception {
|
||||||
|
assertEquals(isCorrectedSearch(), extractor().isCorrectedSearch());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,4 +150,28 @@ public class YoutubeMusicSearchExtractorTest {
|
|||||||
@Nullable @Override public String expectedSearchSuggestion() { return "mega man x3"; }
|
@Nullable @Override public String expectedSearchSuggestion() { return "mega man x3"; }
|
||||||
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
|
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CorrectedSearch extends DefaultSearchExtractorTest {
|
||||||
|
private static SearchExtractor extractor;
|
||||||
|
private static final String QUERY = "duo lipa";
|
||||||
|
private static final String EXPECTED_SUGGESTION = "dua lipa";
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUp() throws Exception {
|
||||||
|
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||||
|
extractor = YouTube.getSearchExtractor(QUERY, singletonList(YoutubeSearchQueryHandlerFactory.MUSIC_SONGS), "");
|
||||||
|
extractor.fetchPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public SearchExtractor extractor() { return extractor; }
|
||||||
|
@Override public StreamingService expectedService() { return YouTube; }
|
||||||
|
@Override public String expectedName() { return QUERY; }
|
||||||
|
@Override public String expectedId() { return QUERY; }
|
||||||
|
@Override public String expectedUrlContains() { return "music.youtube.com/search?q=" + URLEncoder.encode(QUERY); }
|
||||||
|
@Override public String expectedOriginalUrlContains() { return "music.youtube.com/search?q=" + URLEncoder.encode(QUERY); }
|
||||||
|
@Override public String expectedSearchString() { return QUERY; }
|
||||||
|
@Nullable @Override public String expectedSearchSuggestion() { return EXPECTED_SUGGESTION; }
|
||||||
|
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
|
||||||
|
@Override public boolean isCorrectedSearch() { return true; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,29 @@ public class YoutubeSearchExtractorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Suggestion extends DefaultSearchExtractorTest {
|
public static class Suggestion extends DefaultSearchExtractorTest {
|
||||||
|
private static SearchExtractor extractor;
|
||||||
|
private static final String QUERY = "newpip";
|
||||||
|
private static final String EXPECTED_SUGGESTION = "newpipe";
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUp() throws Exception {
|
||||||
|
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||||
|
extractor = YouTube.getSearchExtractor(QUERY, singletonList(VIDEOS), "");
|
||||||
|
extractor.fetchPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public SearchExtractor extractor() { return extractor; }
|
||||||
|
@Override public StreamingService expectedService() { return YouTube; }
|
||||||
|
@Override public String expectedName() { return QUERY; }
|
||||||
|
@Override public String expectedId() { return QUERY; }
|
||||||
|
@Override public String expectedUrlContains() { return "youtube.com/results?search_query=" + QUERY; }
|
||||||
|
@Override public String expectedOriginalUrlContains() { return "youtube.com/results?search_query=" + QUERY; }
|
||||||
|
@Override public String expectedSearchString() { return QUERY; }
|
||||||
|
@Nullable @Override public String expectedSearchSuggestion() { return EXPECTED_SUGGESTION; }
|
||||||
|
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CorrectedSearch extends DefaultSearchExtractorTest {
|
||||||
private static SearchExtractor extractor;
|
private static SearchExtractor extractor;
|
||||||
private static final String QUERY = "pewdeipie";
|
private static final String QUERY = "pewdeipie";
|
||||||
private static final String EXPECTED_SUGGESTION = "pewdiepie";
|
private static final String EXPECTED_SUGGESTION = "pewdiepie";
|
||||||
@ -133,8 +156,8 @@ public class YoutubeSearchExtractorTest {
|
|||||||
@Override public String expectedOriginalUrlContains() { return "youtube.com/results?search_query=" + QUERY; }
|
@Override public String expectedOriginalUrlContains() { return "youtube.com/results?search_query=" + QUERY; }
|
||||||
@Override public String expectedSearchString() { return QUERY; }
|
@Override public String expectedSearchString() { return QUERY; }
|
||||||
@Nullable @Override public String expectedSearchSuggestion() { return EXPECTED_SUGGESTION; }
|
@Nullable @Override public String expectedSearchSuggestion() { return EXPECTED_SUGGESTION; }
|
||||||
|
|
||||||
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
|
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
|
||||||
|
@Override public boolean isCorrectedSearch() { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RandomQueryNoMorePages extends DefaultSearchExtractorTest {
|
public static class RandomQueryNoMorePages extends DefaultSearchExtractorTest {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user