UNPKG

google-sr

Version:

JavaScript / TypeScript tools to fetch Google search results without an API key.

453 lines (440 loc) 16.1 kB
import { CheerioAPI } from 'cheerio'; interface UnitConversionResultNode extends SearchResultNodeLike { type: typeof ResultTypes.UnitConversionResult; from: string; to: string; } /** * Parses unit conversion search results. * * @example * ```ts * import { UnitConversionResult, search } from 'google-sr'; * * const results = await search({ * query: '100 USD to EUR', * parsers: [UnitConversionResult], * }); * ``` * * @param $ - The CheerioAPI instance * @param noPartialResults - Whether to exclude results with missing properties * @returns * - If noPartialResults is true: {@link UnitConversionResultNode} object or null * - If noPartialResults is false: {@link PartialExceptType}<{@link UnitConversionResultNode}> object or null */ declare const UnitConversionResult: ResultParser<UnitConversionResultNode>; interface DictionaryDefinition { definition: string; example?: string; synonyms?: string[]; } interface DictionaryMeaning { partOfSpeech: string; definitions: DictionaryDefinition[]; } interface DictionaryResultNode extends SearchResultNodeLike { type: typeof ResultTypes.DictionaryResult; meanings: DictionaryMeaning[]; phonetic: string; word: string; } /** * Parses dictionary search results. * * @example * ```ts * import { DictionaryResult, search } from 'google-sr'; * * const results = await search({ * query: 'define serendipity', * parsers: [DictionaryResult], * }); * ``` * * @param $ - The CheerioAPI instance * @param noPartialResults - Whether to exclude results with missing properties * @returns * - If noPartialResults is true: {@link DictionaryResultNode} object or null * - If noPartialResults is false: {@link PartialExceptType}<{@link DictionaryResultNode}> object or null */ declare const DictionaryResult: ResultParser<DictionaryResultNode>; interface KnowledgePanelMetadata { label: string; value: string; } interface KnowledgePanelResultNode extends SearchResultNodeLike { type: typeof ResultTypes.KnowledgePanelResult; title: string; description: string; label: string; sourceLink?: string; imageLink?: string; metadata: KnowledgePanelMetadata[]; } /** * Parses knowledge panel search results. * Knowledge panels appear for well-known entities like people, places, and organizations. * * @example * ```ts * import { KnowledgePanelResult, search } from 'google-sr'; * * const results = await search({ * query: 'Albert Einstein', * parsers: [KnowledgePanelResult], * }); * ``` * * @param $ - The CheerioAPI instance * @param noPartialResults - Whether to exclude results with missing properties * @returns * - If noPartialResults is true: {@link KnowledgePanelResultNode} object or null * - If noPartialResults is false: {@link PartialExceptType}<{@link KnowledgePanelResultNode}> object or null */ declare const KnowledgePanelResult: ResultParser<KnowledgePanelResultNode>; interface NewsResultNode extends SearchResultNodeLike { type: typeof ResultTypes.NewsResult; title: string; description: string; link: string; source: string; published_date: string; thumbnail_image?: string; } /** * Parses results from the dedicated News tab in Google Search. * * To use this parser, set the `tbm` query parameter to `'nws'` in the request configuration. * * **NOTE: This parser is not compatible with the other parsers and vice versa.** * * @example * ```ts * import { NewsResult, search } from 'google-sr'; * * const results = await search({ * query: 'latest news on AI', * parsers: [NewsResult], * requestConfig: { * queryParams: { * tbm: 'nws', // Set tbm to nws for news results * }, * }, * }); * ``` * * @param $ - The CheerioAPI instance * @param noPartialResults - Whether to exclude results with missing properties * @returns * - If noPartialResults is true: Array of {@link NewsResultNode} objects * - If noPartialResults is false: Array of {@link PartialExceptType}<{@link NewsResultNode}> objects * - If no results are found: returns an empty array */ declare const NewsResult: ResultParser<NewsResultNode>; interface OrganicResultNode extends SearchResultNodeLike { type: typeof ResultTypes.OrganicResult; title: string; description?: string; link: string; source: string; isAd: boolean; } /** * Parses regular search results. * Despite the "organic" in the name, this parser is used for all regular search results **including ads**. * It is the most commonly used parser and should be used for most search queries. * * @example * ```ts * import { OrganicResult, search } from 'google-sr'; * * const results = await search({ * query: 'google-sr npm package', * parsers: [OrganicResult], * }); * ``` * * @param $ - The CheerioAPI instance * @param noPartialResults - Whether to exclude results with missing properties * @returns * - If noPartialResults is true: Array of {@link OrganicResultNode} objects * - If noPartialResults is false: Array of {@link PartialExceptType}<{@link OrganicResultNode}> objects * - If no results are found: returns an empty array */ declare const OrganicResult: ResultParser<OrganicResultNode>; interface RelatedSearchesResultNode extends SearchResultNodeLike { type: typeof ResultTypes.RelatedSearchesResult; queries: string[]; } /** * Parses related search queries that appear at the bottom of Google search results. * This parser extracts the "Related searches" or similar related query suggestions * that Google displays to help users find similar or relevant topics. * * @example * ```ts * import { RelatedSearchesResult, search } from 'google-sr'; * * const results = await search({ * query: 'nodejs frameworks', * parsers: [RelatedSearchesResult], * }); * // results[0].queries might contain: ["express.js", "react.js", ...] * ``` * * @param $ - The CheerioAPI instance * @param noPartialResults - Whether to exclude results with missing properties * @returns * - If noPartialResults is true: {@link RelatedSearchesResultNode} object or null * - If noPartialResults is false: {@link PartialExceptType}<{@link RelatedSearchesResultNode}> object or null */ declare const RelatedSearchesResult: ResultParser<RelatedSearchesResultNode>; interface TimeResultNode extends SearchResultNodeLike { type: typeof ResultTypes.TimeResult; location: string; time: string; timeInWords: string; } /** * Parses time search results. * * @example * ```ts * import { TimeResult, search } from 'google-sr'; * * const results = await search({ * query: 'time in new york', * parsers: [TimeResult], * }); * ``` * * @param $ - The CheerioAPI instance * @param noPartialResults - Whether to exclude results with missing properties * @returns * - If noPartialResults is true: {@link TimeResultNode} object or null * - If noPartialResults is false: {@link PartialExceptType}<{@link TimeResultNode}> object or null */ declare const TimeResult: ResultParser<TimeResultNode>; interface TranslateResultNode extends SearchResultNodeLike { type: typeof ResultTypes.TranslateResult; sourceLanguage: string; translationLanguage: string; sourceText: string; translatedText: string; } /** * Parses translation search results. * * @example * ```ts * import { TranslateResult, search } from 'google-sr'; * * const results = await search({ * query: 'translate hello to spanish', * parsers: [TranslateResult], * }); * ``` * * @param $ - The CheerioAPI instance * @param noPartialResults - Whether to exclude results with missing properties * @returns * - If noPartialResults is true: {@link TranslateResultNode} object or null * - If noPartialResults is false: {@link PartialExceptType}<{@link TranslateResultNode}> object or null */ declare const TranslateResult: ResultParser<TranslateResultNode>; declare const ResultTypes: { readonly OrganicResult: "ORGANIC"; readonly TranslateResult: "TRANSLATE"; readonly DictionaryResult: "DICTIONARY"; readonly TimeResult: "TIME"; readonly UnitConversionResult: "CONVERSION"; readonly KnowledgePanelResult: "KNOWLEDGE_PANEL"; readonly NewsResult: "NEWS"; readonly RelatedSearchesResult: "RELATED_SEARCHES"; }; type SearchResultNode = OrganicResultNode | TranslateResultNode | DictionaryResultNode | TimeResultNode | UnitConversionResultNode | KnowledgePanelResultNode | NewsResultNode | RelatedSearchesResultNode; interface RequestOptions extends RequestInit { url?: string; queryParams?: Record<string, string> | URLSearchParams; } interface SearchResultNodeLike { type: string; } /** * A ResultParser is a function that takes a CheerioAPI instance and returns an array of search result nodes, a single node, or null if no results are found. * * Note: The return type does not always reflect the actual type that can be returned by the parser. * * Example: The returned node can also be a PartialExceptType<OrganicResultNode> if noPartialResults is false. * * **However, to satisfy the type system, always cast the return type to the expected type.** * * @example * ```ts * const myCustomParser: ResultParser<MyCustomResultNode> = ($, noPartialResults) => { * // your parsing logic here * // make sure to respect the noPartialResults flag * return { * // mandatory if returning a result * type: "MY_CUSTOM_RESULT", * title: "My Custom Result", * // usually these are obtained via parsing the html * // return undefined if noPartialResults is false and the property is not available * description: undefined, * } as MyCustomResultNode; // cast to the expected type to satisfy the type system * } * ``` */ type ResultParser<R extends SearchResultNodeLike = SearchResultNodeLike> = (cheerio: CheerioAPI, noPartialResults: boolean) => R | R[] | null; /** * Search options for single page search */ interface SearchOptions<R extends ResultParser = ResultParser, N extends boolean = false> { /** * The search query string to send to Google. */ query: string; /** * Array of result parsers that determine which types of results to extract. * * Each parser processes the HTML response and extracts specific result types. * Using fewer parsers can improve performance. * * @default [OrganicResult] - Only organic results are parsed if not specified */ parsers?: R[]; /** * Whether to exclude results with missing or undefined properties. * @default false - Partial results are included. */ noPartialResults?: N; /** * Custom HTTP request configuration for the search request. * * Accepts all standard Fetch API options (headers, method, signal, etc.) * plus additional google-sr specific properties. * * @example * ```ts * requestConfig: { * signal: abortController.signal, * queryParams: { tbm: 'nws' }, // this is provided by google-sr * } * ``` */ requestConfig?: RequestOptions; } /** * Configuration options for multi-page search. */ interface SearchOptionsWithPages<R extends ResultParser = ResultParser, N extends boolean = false> extends SearchOptions<R, N> { /** * Specifies which pages to search. * * - **Number**: Total pages to search starting from page 1 * - **Array**: Specific page offsets to search (0 = page 1, 10 = page 2, etc.) * * Google uses cursor-based pagination with increments of 10. * * @example * ```ts * pages: 3 // Searches pages 1, 2, 3 (offsets: 0, 10, 20) * pages: [0, 20] // Searches pages 1 and 3 (offsets: 0, 20) * ``` */ pages: number | number[]; /** * Delay between requests in milliseconds. * * Helps prevent rate limiting by spacing out requests. * Set to 0 to disable delays (not recommended for production). * * @default 1000 - 1 second delay between requests */ delay?: number; } declare const TranslateSourceTextRegex: RegExp; declare const GOOGLE_REDIRECT_URL_PARAM_REGEX: RegExp; declare const GOOGLE_SEARCH_URL = "https://www.google.com/search"; /** * Internal utility type to convert a array type (T[]) to a single type (T) * if T is not an array, it will return T * @private */ type AsArrayElement<T> = T extends Array<infer U> ? U : T; /** * Internal utility type to extract the result type from a ResultParser function * @private */ type ParserResultType<R extends ResultParser> = AsArrayElement<ReturnType<R>>; /** * Internal utility type to create a partial type from a result type * It will make all properties optional except the 'type' property * @internal */ type PartialExceptType<T extends { type: string; }> = Pick<T, "type"> & Omit<Partial<T>, "type">; /** * Internal utility type to extract the search result type from a ResultParser * It will return the type of the result parser, with the 'type' property always present * @private */ type SearchResultTypeFromParser<R extends ResultParser, N extends boolean> = N extends true ? NonNullable<ParserResultType<R>> : PartialExceptType<NonNullable<ParserResultType<R>>>; /** * Performs a Google search and returns parsed results from a single page. * * This is the main search function for single-page searches. It accepts various parsers * to extract different types of results (organic results, news, translations, etc.). * * @example * ```ts * import { search, OrganicResult } from 'google-sr'; * * const results = await search({ * query: 'nodejs tutorial', * // Configure the parsers you want * parsers: [OrganicResult], * noPartialResults: true * }); * ``` * * @param searchOptions - Configuration options for the search * @returns Promise that resolves to an array of parsed search results * @throws {TypeError} When searchOptions is not provided or is invalid */ declare function search<R extends ResultParser, N extends boolean = false>(searchOptions: SearchOptions<R, N>): Promise<SearchResultTypeFromParser<R, N>[]>; /** * Performs a Google search across multiple pages and returns parsed results. * * This function efficiently searches multiple pages by reusing the same parsers * and request configuration. Results are returned as a 2D array where each * sub-array contains results from one page. * * @example * ```ts * import { searchWithPages, OrganicResult } from 'google-sr'; * * // Search first 3 pages * const results = await searchWithPages({ * query: 'machine learning', * parsers: [OrganicResult], * pages: 3, // Will search pages 0, 10, 20 * delay: 1000 // 1 second delay between requests * }); * * // Search specific pages * const specificResults = await searchWithPages({ * query: 'react hooks', * parsers: [OrganicResult], * pages: [0, 20, 40], // Search pages 1, 3, and 5 * }); * ``` * * @param options - Configuration options for the multi-page search * @returns Promise that resolves to a 2D array where each sub-array contains results from one page * @throws {TypeError} When options is not provided or pages parameter is invalid */ declare function searchWithPages<R extends ResultParser = typeof OrganicResult, N extends boolean = false>(options: SearchOptionsWithPages<R, N>): Promise<SearchResultTypeFromParser<R, N>[][]>; export { type DictionaryDefinition, type DictionaryMeaning, DictionaryResult, type DictionaryResultNode, GOOGLE_REDIRECT_URL_PARAM_REGEX, GOOGLE_SEARCH_URL, type KnowledgePanelMetadata, KnowledgePanelResult, type KnowledgePanelResultNode, NewsResult, type NewsResultNode, OrganicResult, type OrganicResultNode, type ParserResultType, type PartialExceptType, RelatedSearchesResult, type RelatedSearchesResultNode, type RequestOptions, type ResultParser, ResultTypes, type SearchOptions, type SearchOptionsWithPages, type SearchResultNode, type SearchResultNodeLike, type SearchResultTypeFromParser, TimeResult, type TimeResultNode, TranslateResult, type TranslateResultNode, TranslateSourceTextRegex, UnitConversionResult, type UnitConversionResultNode, search, searchWithPages };