@galihvsx/gmr-scraper 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/LICENSE +21 -0
- package/README.md +335 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +681 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +724 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +150 -0
- package/dist/index.d.ts +150 -0
- package/dist/index.js +707 -0
- package/dist/index.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cache.ts","../src/rate-limiter.ts","../src/types.ts","../src/errors.ts","../src/extractors.ts","../src/parser.ts","../src/retry.ts","../src/utils.ts","../src/analytics.ts","../src/batch.ts","../src/filters.ts","../src/stream.ts","../src/index.ts"],"names":["SortEnum","calculateAnalytics"],"mappings":"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","file":"index.cjs","sourcesContent":["export interface CacheOptions {\n enabled?: boolean;\n ttl?: number;\n maxSize?: number;\n}\n\ninterface CacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\nexport class Cache<T = any> {\n private cache = new Map<string, CacheEntry<T>>();\n private readonly ttl: number;\n private readonly maxSize: number;\n\n constructor(options: CacheOptions = {}) {\n this.ttl = options.ttl ?? 300000;\n this.maxSize = options.maxSize ?? 100;\n }\n\n set(key: string, value: T): void {\n if (this.cache.size >= this.maxSize) {\n const firstKey = this.cache.keys().next().value;\n if (firstKey) {\n this.cache.delete(firstKey);\n }\n }\n\n this.cache.set(key, {\n value,\n expiresAt: Date.now() + this.ttl,\n });\n }\n\n get(key: string): T | undefined {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return undefined;\n }\n\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return undefined;\n }\n\n return entry.value;\n }\n\n has(key: string): boolean {\n return this.get(key) !== undefined;\n }\n\n delete(key: string): void {\n this.cache.delete(key);\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n size(): number {\n this.cleanup();\n return this.cache.size;\n }\n\n private cleanup(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key);\n }\n }\n }\n}\n\nexport function createCacheKey(\n placeId: string,\n sort: number,\n page: string,\n query: string,\n lang: string\n): string {\n return `${placeId}:${sort}:${page}:${query}:${lang}`;\n}\n","export interface RateLimiterOptions {\n requestsPerSecond?: number;\n burstSize?: number;\n}\n\nexport class RateLimiter {\n private tokens: number;\n private lastRefill: number;\n private readonly requestsPerSecond: number;\n private readonly burstSize: number;\n private readonly refillRate: number;\n\n constructor(options: RateLimiterOptions = {}) {\n this.requestsPerSecond = options.requestsPerSecond ?? 2;\n this.burstSize = options.burstSize ?? 5;\n this.tokens = this.burstSize;\n this.lastRefill = Date.now();\n this.refillRate = 1000 / this.requestsPerSecond;\n }\n\n private refill(): void {\n const now = Date.now();\n const timePassed = now - this.lastRefill;\n const tokensToAdd = Math.floor(timePassed / this.refillRate);\n\n if (tokensToAdd > 0) {\n this.tokens = Math.min(this.burstSize, this.tokens + tokensToAdd);\n this.lastRefill = now;\n }\n }\n\n async acquire(): Promise<void> {\n this.refill();\n\n if (this.tokens > 0) {\n this.tokens--;\n return;\n }\n\n const waitTime = this.refillRate - (Date.now() - this.lastRefill);\n if (waitTime > 0) {\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n return this.acquire();\n }\n }\n\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n await this.acquire();\n return fn();\n }\n}\n","export enum SortEnum {\n relevant = 1,\n newest = 2,\n highest_rating = 3,\n lowest_rating = 4,\n}\n\nexport type SortType = keyof typeof SortEnum;\n\nexport interface ScraperOptions {\n sort_type?: SortType;\n search_query?: string;\n pages?: number | \"max\";\n clean?: boolean;\n lang?: string;\n retry?: RetryOptions;\n cache?: CacheOptions;\n rateLimit?: RateLimitOptions;\n timeout?: number;\n onProgress?: ProgressCallback;\n}\n\nexport interface RetryOptions {\n maxAttempts?: number;\n initialDelay?: number;\n maxDelay?: number;\n backoffMultiplier?: number;\n timeout?: number;\n retryCondition?: (error: Error) => boolean;\n}\n\nexport interface CacheOptions {\n enabled?: boolean;\n ttl?: number;\n maxSize?: number;\n}\n\nexport interface RateLimitOptions {\n requestsPerSecond?: number;\n burstSize?: number;\n}\n\nexport type ProgressCallback = (current: number, total: number | \"max\") => void;\n\nexport interface ReviewTime {\n published: string;\n last_edited: string | null;\n}\n\nexport interface ReviewAuthor {\n name: string;\n profile_url: string;\n url: string;\n id: string;\n}\n\nexport interface ReviewContent {\n rating: number;\n text: string | null;\n original_text?: string | null;\n language: string | null;\n}\n\nexport interface ReviewImageSize {\n width: number;\n height: number;\n}\n\nexport interface ReviewImageLocation {\n friendly: string | null;\n lat: number;\n long: number;\n}\n\nexport interface ReviewImage {\n id: string;\n url: string;\n size: ReviewImageSize;\n location: ReviewImageLocation;\n caption: string | null;\n}\n\nexport interface ReviewResponse {\n text: string;\n time: ReviewTime;\n}\n\nexport interface ParsedReview {\n review_id: string;\n time: ReviewTime;\n author: ReviewAuthor;\n review: ReviewContent;\n images: ReviewImage[] | null;\n source: string;\n response: ReviewResponse | null;\n}\n\nexport interface ReviewAnalytics {\n totalReviews: number;\n averageRating: number;\n ratingDistribution: Record<number, number>;\n reviewsWithText: number;\n reviewsWithImages: number;\n reviewsWithResponse: number;\n}\n\nexport interface BatchResult {\n url: string;\n placeId?: string;\n reviews: ParsedReview[] | any[];\n analytics?: ReviewAnalytics;\n error?: Error;\n}\n\nexport interface FilterOptions {\n minRating?: number;\n maxRating?: number;\n hasText?: boolean;\n hasImages?: boolean;\n hasResponse?: boolean;\n keywords?: string[];\n}\n","export class ScraperError extends Error {\n constructor(message: string, public readonly code?: string) {\n super(message);\n this.name = \"ScraperError\";\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nexport class InvalidUrlError extends ScraperError {\n constructor(message: string) {\n super(message, \"INVALID_URL\");\n this.name = \"InvalidUrlError\";\n }\n}\n\nexport class FetchError extends ScraperError {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly response?: string\n ) {\n super(message, \"FETCH_ERROR\");\n this.name = \"FetchError\";\n }\n}\n\nexport class ParseError extends ScraperError {\n constructor(message: string, public readonly data?: any) {\n super(message, \"PARSE_ERROR\");\n this.name = \"ParseError\";\n }\n}\n\nexport class RateLimitError extends ScraperError {\n constructor(\n message: string = \"Rate limit exceeded\",\n public readonly retryAfter?: number\n ) {\n super(message, \"RATE_LIMIT\");\n this.name = \"RateLimitError\";\n }\n}\n\nexport class TimeoutError extends ScraperError {\n constructor(message: string = \"Request timeout\") {\n super(message, \"TIMEOUT\");\n this.name = \"TimeoutError\";\n }\n}\n","import { SortEnum } from \"./types\";\n\n/**\n * Resolves a Google Maps URL to its canonical form, handling redirects (e.g., goo.gl).\n * @param url - The input URL.\n * @returns The resolved URL.\n */\nexport async function resolveUrl(url: string): Promise<string> {\n if (url.includes(\"goo.gl\") || url.includes(\"maps.app.goo.gl\")) {\n const response = await fetch(url, { redirect: \"follow\", method: \"HEAD\" });\n return response.url;\n }\n return url;\n}\n\n/**\n * Extracts the Place ID (LID:FID) from a Google Maps URL.\n * Matches patterns like !1s0x...:0x...\n * @param url - The Google Maps URL.\n * @returns The extracted Place ID.\n * @throws Error if the ID cannot be found.\n */\nexport function extractPlaceId(url: string): string {\n const match1 = url.match(/!1s(0x[0-9a-fA-F]+:0x[0-9a-fA-F]+)/);\n if (match1 && match1[1]) {\n return match1[1];\n }\n\n const match2 = url.match(/!1s([a-zA-Z0-9_:]+)!/);\n if (match2 && match2[1]) {\n return match2[1];\n }\n\n throw new Error(\n \"Could not extract Place ID from URL. Please ensure it is a valid Google Maps Place URL.\"\n );\n}\n\n/**\n * Constructs the RPC URL for fetching reviews.\n * @param placeId - The extracted Place ID.\n * @param sort - Sort entum value.\n * @param nextPageToken - Token for the next page.\n * @param searchQuery - Query to filter reviews.\n * @returns The API URL.\n */\nfunction hexToDec(hex: string): string {\n return BigInt(hex).toString();\n}\n\n/**\n * Constructs the RPC URL for fetching reviews.\n * Uses the listentitiesreviews endpoint which uses Decimal IDs.\n */\nexport function buildRpcUrl(\n placeId: string,\n sort: SortEnum,\n nextPageToken: string = \"\",\n searchQuery: string = \"\",\n lang: string = \"en\"\n): string {\n const parts = placeId.split(\":\");\n if (parts.length !== 2) {\n throw new Error(\n `Invalid Place ID format for listentitiesreviews: ${placeId}`\n );\n }\n\n const h1 = hexToDec(parts[0]!);\n const h2 = hexToDec(parts[1]!);\n\n const constantToken = \"dzvaXrvAMImImAXHsLPICA\";\n\n const paginationBlock = nextPageToken\n ? `!2m2!2i10!3s${nextPageToken}`\n : `!2m1!2i10`;\n\n return `https://www.google.com/maps/preview/review/listentitiesreviews?authuser=0&hl=${lang}&gl=in&pb=!1m2!1y${h1}!2y${h2}${paginationBlock}!3e${sort}!4m5!3b1!4b1!5b1!6b1!7b1!5m2!1s${constantToken}!7e81`;\n}\n","import type { ParsedReview } from \"./types\";\n\n/**\n * Parses an array of raw reviews from Google Maps (listentitiesreviews endpoint).\n * @param reviews - The array of reviews to parse.\n * @returns An array of parsed review objects.\n */\nexport function parseReviews(reviews: any[]): ParsedReview[] {\n return reviews.map((review: any) => {\n const authorInfo = review[0] || [];\n const images = null;\n const response = null;\n\n return {\n review_id: review[10] as string,\n time: {\n published: review[1] as string,\n last_edited: null,\n },\n author: {\n name: authorInfo[1] as string,\n profile_url: authorInfo[0] as string,\n url: authorInfo[0] as string,\n id: review[6] as string,\n },\n review: {\n rating: review[4] as number,\n text: parseText(review[3] as string | null).text,\n original_text: parseText(review[3] as string | null).original_text,\n language: review[32] as string | null,\n },\n images: images,\n source: review[10] as string,\n response: response,\n };\n });\n}\n\nfunction parseText(text: string | null): {\n text: string | null;\n original_text: string | null;\n} {\n if (!text) return { text: null, original_text: null };\n\n const splitPattern = /\\n\\n\\((.+?)\\)\\n/g;\n const match = splitPattern.exec(text);\n\n if (match) {\n const splitIndex = match.index;\n const originalHeaderLength = match[0].length;\n\n const firstPart = text.substring(0, splitIndex);\n const secondPart = text.substring(splitIndex + originalHeaderLength);\n\n const translationParamMatch = firstPart.match(/^\\((.+?)\\) /);\n let translatedText = firstPart;\n\n if (translationParamMatch) {\n translatedText = firstPart.substring(translationParamMatch[0].length);\n }\n\n return {\n text: translatedText,\n original_text: secondPart,\n };\n }\n\n return { text: text, original_text: null };\n}\n","import { TimeoutError } from \"./errors\";\n\nexport interface RetryOptions {\n maxAttempts?: number;\n initialDelay?: number;\n maxDelay?: number;\n backoffMultiplier?: number;\n timeout?: number;\n retryCondition?: (error: Error) => boolean;\n}\n\nconst DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {\n maxAttempts: 3,\n initialDelay: 1000,\n maxDelay: 10000,\n backoffMultiplier: 2,\n timeout: 30000,\n retryCondition: (error: Error) => {\n if (error.name === \"InvalidUrlError\") return false;\n if (error.name === \"ParseError\") return false;\n return true;\n },\n};\n\nasync function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction calculateDelay(\n attempt: number,\n initialDelay: number,\n maxDelay: number,\n backoffMultiplier: number\n): number {\n const delay = initialDelay * Math.pow(backoffMultiplier, attempt - 1);\n return Math.min(delay, maxDelay);\n}\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<T> {\n const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };\n let lastError: Error;\n\n for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {\n try {\n if (opts.timeout) {\n return await withTimeout(fn(), opts.timeout);\n }\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (attempt === opts.maxAttempts || !opts.retryCondition(lastError)) {\n throw lastError;\n }\n\n const delay = calculateDelay(\n attempt,\n opts.initialDelay,\n opts.maxDelay,\n opts.backoffMultiplier\n );\n\n console.warn(\n `Attempt ${attempt}/${opts.maxAttempts} failed: ${lastError.message}. Retrying in ${delay}ms...`\n );\n\n await sleep(delay);\n }\n }\n\n throw lastError!;\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number\n): Promise<T> {\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new TimeoutError(`Operation timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n });\n\n return Promise.race([promise, timeoutPromise]);\n}\n","import { Cache, createCacheKey } from \"./cache\";\nimport { FetchError, InvalidUrlError } from \"./errors\";\nimport { buildRpcUrl, extractPlaceId, resolveUrl } from \"./extractors\";\nimport { parseReviews } from \"./parser\";\nimport { RateLimiter } from \"./rate-limiter\";\nimport { withRetry } from \"./retry\";\nimport {\n SortEnum,\n type ParsedReview,\n type ProgressCallback,\n type RetryOptions,\n type SortType,\n} from \"./types\";\n\n/**\n * Validates the scraper parameters.\n */\nexport function validateParams(\n url: string,\n sortType: SortType | undefined,\n pages: number | \"max\" | undefined,\n clean: boolean | undefined\n): void {\n if (!url) {\n throw new InvalidUrlError(\"URL is required\");\n }\n\n if (sortType && !SortEnum[sortType]) {\n throw new InvalidUrlError(\n `Invalid sort type: ${sortType}. Valid options: ${Object.keys(SortEnum)\n .filter((k) => isNaN(Number(k)))\n .join(\", \")}`\n );\n }\n\n if (\n pages !== undefined &&\n pages !== \"max\" &&\n (typeof pages !== \"number\" || pages < 1)\n ) {\n throw new InvalidUrlError(\"Pages must be 'max' or a positive number\");\n }\n}\n\n/**\n * Fetches reviews from the API.\n */\nexport async function fetchReviews(\n placeId: string,\n sort: SortEnum,\n nextPageToken: string = \"\",\n searchQuery: string = \"\",\n lang: string = \"en\",\n cache?: Cache,\n rateLimiter?: RateLimiter,\n retryOptions?: RetryOptions\n): Promise<{ data: any[]; nextPageToken: string | null }> {\n const cacheKey = cache\n ? createCacheKey(placeId, sort, nextPageToken, searchQuery, lang)\n : \"\";\n\n if (cache && cacheKey) {\n const cached = cache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n\n const fetchFn = async () => {\n const apiUrl = buildRpcUrl(placeId, sort, nextPageToken, searchQuery, lang);\n\n const actualFetch = async () => {\n const response = await fetch(apiUrl, {\n headers: {\n \"User-Agent\":\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\",\n },\n });\n\n if (!response.ok) {\n throw new FetchError(\n `Failed to fetch reviews: ${response.statusText}`,\n response.status\n );\n }\n\n const textData = await response.text();\n const cleanJson = textData.replace(/^\\)\\]\\}'/, \"\");\n\n let parsedData;\n try {\n parsedData = JSON.parse(cleanJson);\n } catch (e) {\n console.error(\"Failed to parse JSON:\", cleanJson.substring(0, 100));\n throw new FetchError(\"Failed to parse API response\");\n }\n\n if (!parsedData || !Array.isArray(parsedData)) {\n console.warn(\"Unexpected response structure:\", parsedData);\n return { data: [], nextPageToken: null };\n }\n\n const reviews = parsedData[2] || [];\n const nextToken = parsedData[1] || null;\n\n return { data: reviews, nextPageToken: nextToken };\n };\n\n if (rateLimiter) {\n return rateLimiter.execute(actualFetch);\n }\n return actualFetch();\n };\n\n const result = retryOptions\n ? await withRetry(fetchFn, retryOptions)\n : await fetchFn();\n\n if (cache && cacheKey) {\n cache.set(cacheKey, result);\n }\n\n return result;\n}\n\n/**\n * Paginates through reviews.\n */\nexport async function paginateReviews(\n url: string,\n sort: SortEnum,\n pages: number | \"max\",\n searchQuery: string,\n clean: boolean,\n lang: string = \"en\",\n cache?: Cache,\n rateLimiter?: RateLimiter,\n retryOptions?: RetryOptions,\n onProgress?: ProgressCallback\n): Promise<any[] | ParsedReview[]> {\n const resolvedUrl = await resolveUrl(url);\n const placeId = extractPlaceId(resolvedUrl);\n\n const initial = await fetchReviews(\n placeId,\n sort,\n \"\",\n searchQuery,\n lang,\n cache,\n rateLimiter,\n retryOptions\n );\n let allReviews = [...initial.data];\n let nextPageToken = initial.nextPageToken;\n\n if (onProgress) {\n onProgress(1, pages);\n }\n\n if (pages === 1 || !nextPageToken) {\n return clean ? parseReviews(allReviews) : allReviews;\n }\n\n let currentPage = 2;\n const maxPages = pages === \"max\" ? Infinity : pages;\n\n while (nextPageToken && currentPage <= maxPages) {\n if (!rateLimiter) {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n\n try {\n const nextBatch = await fetchReviews(\n placeId,\n sort,\n nextPageToken,\n searchQuery,\n lang,\n cache,\n rateLimiter,\n retryOptions\n );\n allReviews = [...allReviews, ...nextBatch.data];\n nextPageToken = nextBatch.nextPageToken;\n\n if (onProgress) {\n onProgress(currentPage, pages);\n }\n\n if (!nextBatch.data.length && !nextPageToken) {\n break;\n }\n } catch (e) {\n console.error(`Error scraping page ${currentPage}:`, e);\n break;\n }\n\n currentPage++;\n }\n\n return clean ? parseReviews(allReviews) : allReviews;\n}\n","import type { ParsedReview, ReviewAnalytics } from \"./types\";\n\nexport function calculateAnalytics(reviews: ParsedReview[]): ReviewAnalytics {\n const totalReviews = reviews.length;\n const ratingDistribution: Record<number, number> = {\n 1: 0,\n 2: 0,\n 3: 0,\n 4: 0,\n 5: 0,\n };\n\n let totalRating = 0;\n let reviewsWithText = 0;\n let reviewsWithImages = 0;\n let reviewsWithResponse = 0;\n\n for (const review of reviews) {\n const rating = review.review.rating;\n totalRating += rating;\n ratingDistribution[rating] = (ratingDistribution[rating] || 0) + 1;\n\n if (review.review.text) reviewsWithText++;\n if (review.images && review.images.length > 0) reviewsWithImages++;\n if (review.response) reviewsWithResponse++;\n }\n\n return {\n totalReviews,\n averageRating:\n totalReviews > 0 ? Number((totalRating / totalReviews).toFixed(2)) : 0,\n ratingDistribution,\n reviewsWithText,\n reviewsWithImages,\n reviewsWithResponse,\n };\n}\n\nexport function getTopRatedReviews(\n reviews: ParsedReview[],\n limit: number = 10\n): ParsedReview[] {\n return [...reviews]\n .sort((a, b) => b.review.rating - a.review.rating)\n .slice(0, limit);\n}\n\nexport function getRecentReviews(\n reviews: ParsedReview[],\n limit: number = 10\n): ParsedReview[] {\n return [...reviews]\n .sort((a, b) => {\n const dateA = new Date(a.time.published).getTime();\n const dateB = new Date(b.time.published).getTime();\n return dateB - dateA;\n })\n .slice(0, limit);\n}\n\nexport function groupByRating(\n reviews: ParsedReview[]\n): Record<number, ParsedReview[]> {\n const grouped: Record<number, ParsedReview[]> = {\n 1: [],\n 2: [],\n 3: [],\n 4: [],\n 5: [],\n };\n\n for (const review of reviews) {\n const rating = review.review.rating;\n if (grouped[rating]) {\n grouped[rating].push(review);\n }\n }\n\n return grouped;\n}\n","import { extractPlaceId, resolveUrl } from \"./extractors\";\nimport { scraper } from \"./index\";\nimport type {\n BatchResult,\n ParsedReview,\n ReviewAnalytics,\n ScraperOptions,\n} from \"./types\";\n\nexport interface BatchOptions extends Omit<ScraperOptions, \"onProgress\"> {\n concurrency?: number;\n onProgress?: (completed: number, total: number, url: string) => void;\n includeAnalytics?: boolean;\n}\n\nexport async function batchScraper(\n urls: string[],\n options: BatchOptions = {}\n): Promise<BatchResult[]> {\n const {\n concurrency = 3,\n onProgress,\n includeAnalytics = false,\n ...scraperOptions\n } = options;\n\n const results: BatchResult[] = [];\n const queue = [...urls];\n let completed = 0;\n\n const processBatch = async (url: string): Promise<BatchResult> => {\n try {\n const resolvedUrl = await resolveUrl(url);\n const placeId = extractPlaceId(resolvedUrl);\n\n const reviews = await scraper(url, scraperOptions);\n\n const result: BatchResult = {\n url,\n placeId,\n reviews,\n };\n\n if (includeAnalytics && scraperOptions.clean) {\n result.analytics = calculateAnalytics(reviews as ParsedReview[]);\n }\n\n completed++;\n if (onProgress) {\n onProgress(completed, urls.length, url);\n }\n\n return result;\n } catch (error) {\n completed++;\n if (onProgress) {\n onProgress(completed, urls.length, url);\n }\n\n return {\n url,\n reviews: [],\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n };\n\n const workers: Promise<void>[] = [];\n for (let i = 0; i < concurrency; i++) {\n workers.push(\n (async () => {\n while (queue.length > 0) {\n const url = queue.shift();\n if (url) {\n const result = await processBatch(url);\n results.push(result);\n }\n }\n })()\n );\n }\n\n await Promise.all(workers);\n\n return results;\n}\n\nfunction calculateAnalytics(reviews: ParsedReview[]): ReviewAnalytics {\n const totalReviews = reviews.length;\n const ratingDistribution: Record<number, number> = {\n 1: 0,\n 2: 0,\n 3: 0,\n 4: 0,\n 5: 0,\n };\n\n let totalRating = 0;\n let reviewsWithText = 0;\n let reviewsWithImages = 0;\n let reviewsWithResponse = 0;\n\n for (const review of reviews) {\n const rating = review.review.rating;\n totalRating += rating;\n ratingDistribution[rating] = (ratingDistribution[rating] || 0) + 1;\n\n if (review.review.text) reviewsWithText++;\n if (review.images && review.images.length > 0) reviewsWithImages++;\n if (review.response) reviewsWithResponse++;\n }\n\n return {\n totalReviews,\n averageRating: totalReviews > 0 ? totalRating / totalReviews : 0,\n ratingDistribution,\n reviewsWithText,\n reviewsWithImages,\n reviewsWithResponse,\n };\n}\n","import type { FilterOptions, ParsedReview } from \"./types\";\n\nexport function filterReviews(\n reviews: ParsedReview[],\n filters: FilterOptions\n): ParsedReview[] {\n return reviews.filter((review) => {\n if (\n filters.minRating !== undefined &&\n review.review.rating < filters.minRating\n ) {\n return false;\n }\n\n if (\n filters.maxRating !== undefined &&\n review.review.rating > filters.maxRating\n ) {\n return false;\n }\n\n if (filters.hasText !== undefined) {\n const hasText = !!review.review.text;\n if (filters.hasText !== hasText) {\n return false;\n }\n }\n\n if (filters.hasImages !== undefined) {\n const hasImages = !!review.images && review.images.length > 0;\n if (filters.hasImages !== hasImages) {\n return false;\n }\n }\n\n if (filters.hasResponse !== undefined) {\n const hasResponse = !!review.response;\n if (filters.hasResponse !== hasResponse) {\n return false;\n }\n }\n\n if (filters.keywords && filters.keywords.length > 0) {\n const text = (review.review.text || \"\").toLowerCase();\n const hasKeyword = filters.keywords.some((keyword) =>\n text.includes(keyword.toLowerCase())\n );\n if (!hasKeyword) {\n return false;\n }\n }\n\n return true;\n });\n}\n\nexport function searchReviews(\n reviews: ParsedReview[],\n query: string\n): ParsedReview[] {\n const lowerQuery = query.toLowerCase();\n return reviews.filter((review) => {\n const text = (review.review.text || \"\").toLowerCase();\n const authorName = review.author.name.toLowerCase();\n return text.includes(lowerQuery) || authorName.includes(lowerQuery);\n });\n}\n","import { Cache } from \"./cache\";\nimport { extractPlaceId, resolveUrl } from \"./extractors\";\nimport { parseReviews } from \"./parser\";\nimport { RateLimiter } from \"./rate-limiter\";\nimport { SortEnum, type ParsedReview, type ScraperOptions } from \"./types\";\nimport { fetchReviews, validateParams } from \"./utils\";\n\nexport async function* scrapeStream(\n url: string,\n options: ScraperOptions = {}\n): AsyncGenerator<ParsedReview | any, void, unknown> {\n const {\n sort_type = \"relevant\",\n search_query = \"\",\n pages = \"max\",\n clean = false,\n lang = \"en\",\n retry,\n cache: cacheOptions,\n rateLimit,\n } = options;\n\n validateParams(url, sort_type, pages, clean);\n\n const sort = SortEnum[sort_type];\n const resolvedUrl = await resolveUrl(url);\n const placeId = extractPlaceId(resolvedUrl);\n\n const cache = cacheOptions?.enabled ? new Cache(cacheOptions) : undefined;\n const rateLimiter = rateLimit ? new RateLimiter(rateLimit) : undefined;\n\n const retryOptions = {\n ...retry,\n };\n\n let nextPageToken: string | null = \"\";\n let currentPage = 1;\n const maxPages = pages === \"max\" ? Infinity : pages;\n\n while (currentPage <= maxPages) {\n const result = await fetchReviews(\n placeId,\n sort,\n nextPageToken || \"\",\n search_query,\n lang,\n cache,\n rateLimiter,\n retryOptions\n );\n\n const reviews = clean ? parseReviews(result.data) : result.data;\n\n for (const review of reviews) {\n yield review;\n }\n\n nextPageToken = result.nextPageToken;\n\n if (!nextPageToken || !result.data.length) {\n break;\n }\n\n if (!rateLimiter && currentPage < maxPages) {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n\n currentPage++;\n }\n}\n","import { Cache } from \"./cache\";\nimport { RateLimiter } from \"./rate-limiter\";\nimport { SortEnum, type ScraperOptions, type SortType } from \"./types\";\nimport { paginateReviews, validateParams } from \"./utils\";\n\nexport * from \"./analytics\";\nexport * from \"./batch\";\nexport * from \"./errors\";\nexport * from \"./filters\";\nexport * from \"./stream\";\nexport * from \"./types\";\n\nexport async function scraper(\n url: string,\n options: ScraperOptions = {}\n): Promise<any> {\n const {\n sort_type = \"relevant\" as SortType,\n search_query = \"\",\n pages = \"max\",\n clean = false,\n lang = \"en\",\n retry,\n cache: cacheOptions,\n rateLimit,\n timeout,\n onProgress,\n } = options;\n\n validateParams(url, sort_type, pages, clean);\n\n const sort = SortEnum[sort_type];\n\n const cache = cacheOptions?.enabled ? new Cache(cacheOptions) : undefined;\n const rateLimiter = rateLimit ? new RateLimiter(rateLimit) : undefined;\n\n const retryOptions = {\n timeout,\n ...retry,\n };\n\n try {\n return await paginateReviews(\n url,\n sort,\n pages,\n search_query,\n clean,\n lang,\n cache,\n rateLimiter,\n retryOptions,\n onProgress\n );\n } catch (e) {\n console.error(\"Scraper Error:\", e);\n throw e;\n }\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
declare enum SortEnum {
|
|
2
|
+
relevant = 1,
|
|
3
|
+
newest = 2,
|
|
4
|
+
highest_rating = 3,
|
|
5
|
+
lowest_rating = 4
|
|
6
|
+
}
|
|
7
|
+
type SortType = keyof typeof SortEnum;
|
|
8
|
+
interface ScraperOptions {
|
|
9
|
+
sort_type?: SortType;
|
|
10
|
+
search_query?: string;
|
|
11
|
+
pages?: number | "max";
|
|
12
|
+
clean?: boolean;
|
|
13
|
+
lang?: string;
|
|
14
|
+
retry?: RetryOptions;
|
|
15
|
+
cache?: CacheOptions;
|
|
16
|
+
rateLimit?: RateLimitOptions;
|
|
17
|
+
timeout?: number;
|
|
18
|
+
onProgress?: ProgressCallback;
|
|
19
|
+
}
|
|
20
|
+
interface RetryOptions {
|
|
21
|
+
maxAttempts?: number;
|
|
22
|
+
initialDelay?: number;
|
|
23
|
+
maxDelay?: number;
|
|
24
|
+
backoffMultiplier?: number;
|
|
25
|
+
timeout?: number;
|
|
26
|
+
retryCondition?: (error: Error) => boolean;
|
|
27
|
+
}
|
|
28
|
+
interface CacheOptions {
|
|
29
|
+
enabled?: boolean;
|
|
30
|
+
ttl?: number;
|
|
31
|
+
maxSize?: number;
|
|
32
|
+
}
|
|
33
|
+
interface RateLimitOptions {
|
|
34
|
+
requestsPerSecond?: number;
|
|
35
|
+
burstSize?: number;
|
|
36
|
+
}
|
|
37
|
+
type ProgressCallback = (current: number, total: number | "max") => void;
|
|
38
|
+
interface ReviewTime {
|
|
39
|
+
published: string;
|
|
40
|
+
last_edited: string | null;
|
|
41
|
+
}
|
|
42
|
+
interface ReviewAuthor {
|
|
43
|
+
name: string;
|
|
44
|
+
profile_url: string;
|
|
45
|
+
url: string;
|
|
46
|
+
id: string;
|
|
47
|
+
}
|
|
48
|
+
interface ReviewContent {
|
|
49
|
+
rating: number;
|
|
50
|
+
text: string | null;
|
|
51
|
+
original_text?: string | null;
|
|
52
|
+
language: string | null;
|
|
53
|
+
}
|
|
54
|
+
interface ReviewImageSize {
|
|
55
|
+
width: number;
|
|
56
|
+
height: number;
|
|
57
|
+
}
|
|
58
|
+
interface ReviewImageLocation {
|
|
59
|
+
friendly: string | null;
|
|
60
|
+
lat: number;
|
|
61
|
+
long: number;
|
|
62
|
+
}
|
|
63
|
+
interface ReviewImage {
|
|
64
|
+
id: string;
|
|
65
|
+
url: string;
|
|
66
|
+
size: ReviewImageSize;
|
|
67
|
+
location: ReviewImageLocation;
|
|
68
|
+
caption: string | null;
|
|
69
|
+
}
|
|
70
|
+
interface ReviewResponse {
|
|
71
|
+
text: string;
|
|
72
|
+
time: ReviewTime;
|
|
73
|
+
}
|
|
74
|
+
interface ParsedReview {
|
|
75
|
+
review_id: string;
|
|
76
|
+
time: ReviewTime;
|
|
77
|
+
author: ReviewAuthor;
|
|
78
|
+
review: ReviewContent;
|
|
79
|
+
images: ReviewImage[] | null;
|
|
80
|
+
source: string;
|
|
81
|
+
response: ReviewResponse | null;
|
|
82
|
+
}
|
|
83
|
+
interface ReviewAnalytics {
|
|
84
|
+
totalReviews: number;
|
|
85
|
+
averageRating: number;
|
|
86
|
+
ratingDistribution: Record<number, number>;
|
|
87
|
+
reviewsWithText: number;
|
|
88
|
+
reviewsWithImages: number;
|
|
89
|
+
reviewsWithResponse: number;
|
|
90
|
+
}
|
|
91
|
+
interface BatchResult {
|
|
92
|
+
url: string;
|
|
93
|
+
placeId?: string;
|
|
94
|
+
reviews: ParsedReview[] | any[];
|
|
95
|
+
analytics?: ReviewAnalytics;
|
|
96
|
+
error?: Error;
|
|
97
|
+
}
|
|
98
|
+
interface FilterOptions {
|
|
99
|
+
minRating?: number;
|
|
100
|
+
maxRating?: number;
|
|
101
|
+
hasText?: boolean;
|
|
102
|
+
hasImages?: boolean;
|
|
103
|
+
hasResponse?: boolean;
|
|
104
|
+
keywords?: string[];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
declare function calculateAnalytics(reviews: ParsedReview[]): ReviewAnalytics;
|
|
108
|
+
declare function getTopRatedReviews(reviews: ParsedReview[], limit?: number): ParsedReview[];
|
|
109
|
+
declare function getRecentReviews(reviews: ParsedReview[], limit?: number): ParsedReview[];
|
|
110
|
+
declare function groupByRating(reviews: ParsedReview[]): Record<number, ParsedReview[]>;
|
|
111
|
+
|
|
112
|
+
interface BatchOptions extends Omit<ScraperOptions, "onProgress"> {
|
|
113
|
+
concurrency?: number;
|
|
114
|
+
onProgress?: (completed: number, total: number, url: string) => void;
|
|
115
|
+
includeAnalytics?: boolean;
|
|
116
|
+
}
|
|
117
|
+
declare function batchScraper(urls: string[], options?: BatchOptions): Promise<BatchResult[]>;
|
|
118
|
+
|
|
119
|
+
declare class ScraperError extends Error {
|
|
120
|
+
readonly code?: string | undefined;
|
|
121
|
+
constructor(message: string, code?: string | undefined);
|
|
122
|
+
}
|
|
123
|
+
declare class InvalidUrlError extends ScraperError {
|
|
124
|
+
constructor(message: string);
|
|
125
|
+
}
|
|
126
|
+
declare class FetchError extends ScraperError {
|
|
127
|
+
readonly statusCode?: number | undefined;
|
|
128
|
+
readonly response?: string | undefined;
|
|
129
|
+
constructor(message: string, statusCode?: number | undefined, response?: string | undefined);
|
|
130
|
+
}
|
|
131
|
+
declare class ParseError extends ScraperError {
|
|
132
|
+
readonly data?: any | undefined;
|
|
133
|
+
constructor(message: string, data?: any | undefined);
|
|
134
|
+
}
|
|
135
|
+
declare class RateLimitError extends ScraperError {
|
|
136
|
+
readonly retryAfter?: number | undefined;
|
|
137
|
+
constructor(message?: string, retryAfter?: number | undefined);
|
|
138
|
+
}
|
|
139
|
+
declare class TimeoutError extends ScraperError {
|
|
140
|
+
constructor(message?: string);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
declare function filterReviews(reviews: ParsedReview[], filters: FilterOptions): ParsedReview[];
|
|
144
|
+
declare function searchReviews(reviews: ParsedReview[], query: string): ParsedReview[];
|
|
145
|
+
|
|
146
|
+
declare function scrapeStream(url: string, options?: ScraperOptions): AsyncGenerator<ParsedReview | any, void, unknown>;
|
|
147
|
+
|
|
148
|
+
declare function scraper(url: string, options?: ScraperOptions): Promise<any>;
|
|
149
|
+
|
|
150
|
+
export { type BatchOptions, type BatchResult, type CacheOptions, FetchError, type FilterOptions, InvalidUrlError, ParseError, type ParsedReview, type ProgressCallback, RateLimitError, type RateLimitOptions, type RetryOptions, type ReviewAnalytics, type ReviewAuthor, type ReviewContent, type ReviewImage, type ReviewImageLocation, type ReviewImageSize, type ReviewResponse, type ReviewTime, ScraperError, type ScraperOptions, SortEnum, type SortType, TimeoutError, batchScraper, calculateAnalytics, filterReviews, getRecentReviews, getTopRatedReviews, groupByRating, scrapeStream, scraper, searchReviews };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
declare enum SortEnum {
|
|
2
|
+
relevant = 1,
|
|
3
|
+
newest = 2,
|
|
4
|
+
highest_rating = 3,
|
|
5
|
+
lowest_rating = 4
|
|
6
|
+
}
|
|
7
|
+
type SortType = keyof typeof SortEnum;
|
|
8
|
+
interface ScraperOptions {
|
|
9
|
+
sort_type?: SortType;
|
|
10
|
+
search_query?: string;
|
|
11
|
+
pages?: number | "max";
|
|
12
|
+
clean?: boolean;
|
|
13
|
+
lang?: string;
|
|
14
|
+
retry?: RetryOptions;
|
|
15
|
+
cache?: CacheOptions;
|
|
16
|
+
rateLimit?: RateLimitOptions;
|
|
17
|
+
timeout?: number;
|
|
18
|
+
onProgress?: ProgressCallback;
|
|
19
|
+
}
|
|
20
|
+
interface RetryOptions {
|
|
21
|
+
maxAttempts?: number;
|
|
22
|
+
initialDelay?: number;
|
|
23
|
+
maxDelay?: number;
|
|
24
|
+
backoffMultiplier?: number;
|
|
25
|
+
timeout?: number;
|
|
26
|
+
retryCondition?: (error: Error) => boolean;
|
|
27
|
+
}
|
|
28
|
+
interface CacheOptions {
|
|
29
|
+
enabled?: boolean;
|
|
30
|
+
ttl?: number;
|
|
31
|
+
maxSize?: number;
|
|
32
|
+
}
|
|
33
|
+
interface RateLimitOptions {
|
|
34
|
+
requestsPerSecond?: number;
|
|
35
|
+
burstSize?: number;
|
|
36
|
+
}
|
|
37
|
+
type ProgressCallback = (current: number, total: number | "max") => void;
|
|
38
|
+
interface ReviewTime {
|
|
39
|
+
published: string;
|
|
40
|
+
last_edited: string | null;
|
|
41
|
+
}
|
|
42
|
+
interface ReviewAuthor {
|
|
43
|
+
name: string;
|
|
44
|
+
profile_url: string;
|
|
45
|
+
url: string;
|
|
46
|
+
id: string;
|
|
47
|
+
}
|
|
48
|
+
interface ReviewContent {
|
|
49
|
+
rating: number;
|
|
50
|
+
text: string | null;
|
|
51
|
+
original_text?: string | null;
|
|
52
|
+
language: string | null;
|
|
53
|
+
}
|
|
54
|
+
interface ReviewImageSize {
|
|
55
|
+
width: number;
|
|
56
|
+
height: number;
|
|
57
|
+
}
|
|
58
|
+
interface ReviewImageLocation {
|
|
59
|
+
friendly: string | null;
|
|
60
|
+
lat: number;
|
|
61
|
+
long: number;
|
|
62
|
+
}
|
|
63
|
+
interface ReviewImage {
|
|
64
|
+
id: string;
|
|
65
|
+
url: string;
|
|
66
|
+
size: ReviewImageSize;
|
|
67
|
+
location: ReviewImageLocation;
|
|
68
|
+
caption: string | null;
|
|
69
|
+
}
|
|
70
|
+
interface ReviewResponse {
|
|
71
|
+
text: string;
|
|
72
|
+
time: ReviewTime;
|
|
73
|
+
}
|
|
74
|
+
interface ParsedReview {
|
|
75
|
+
review_id: string;
|
|
76
|
+
time: ReviewTime;
|
|
77
|
+
author: ReviewAuthor;
|
|
78
|
+
review: ReviewContent;
|
|
79
|
+
images: ReviewImage[] | null;
|
|
80
|
+
source: string;
|
|
81
|
+
response: ReviewResponse | null;
|
|
82
|
+
}
|
|
83
|
+
interface ReviewAnalytics {
|
|
84
|
+
totalReviews: number;
|
|
85
|
+
averageRating: number;
|
|
86
|
+
ratingDistribution: Record<number, number>;
|
|
87
|
+
reviewsWithText: number;
|
|
88
|
+
reviewsWithImages: number;
|
|
89
|
+
reviewsWithResponse: number;
|
|
90
|
+
}
|
|
91
|
+
interface BatchResult {
|
|
92
|
+
url: string;
|
|
93
|
+
placeId?: string;
|
|
94
|
+
reviews: ParsedReview[] | any[];
|
|
95
|
+
analytics?: ReviewAnalytics;
|
|
96
|
+
error?: Error;
|
|
97
|
+
}
|
|
98
|
+
interface FilterOptions {
|
|
99
|
+
minRating?: number;
|
|
100
|
+
maxRating?: number;
|
|
101
|
+
hasText?: boolean;
|
|
102
|
+
hasImages?: boolean;
|
|
103
|
+
hasResponse?: boolean;
|
|
104
|
+
keywords?: string[];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
declare function calculateAnalytics(reviews: ParsedReview[]): ReviewAnalytics;
|
|
108
|
+
declare function getTopRatedReviews(reviews: ParsedReview[], limit?: number): ParsedReview[];
|
|
109
|
+
declare function getRecentReviews(reviews: ParsedReview[], limit?: number): ParsedReview[];
|
|
110
|
+
declare function groupByRating(reviews: ParsedReview[]): Record<number, ParsedReview[]>;
|
|
111
|
+
|
|
112
|
+
interface BatchOptions extends Omit<ScraperOptions, "onProgress"> {
|
|
113
|
+
concurrency?: number;
|
|
114
|
+
onProgress?: (completed: number, total: number, url: string) => void;
|
|
115
|
+
includeAnalytics?: boolean;
|
|
116
|
+
}
|
|
117
|
+
declare function batchScraper(urls: string[], options?: BatchOptions): Promise<BatchResult[]>;
|
|
118
|
+
|
|
119
|
+
declare class ScraperError extends Error {
|
|
120
|
+
readonly code?: string | undefined;
|
|
121
|
+
constructor(message: string, code?: string | undefined);
|
|
122
|
+
}
|
|
123
|
+
declare class InvalidUrlError extends ScraperError {
|
|
124
|
+
constructor(message: string);
|
|
125
|
+
}
|
|
126
|
+
declare class FetchError extends ScraperError {
|
|
127
|
+
readonly statusCode?: number | undefined;
|
|
128
|
+
readonly response?: string | undefined;
|
|
129
|
+
constructor(message: string, statusCode?: number | undefined, response?: string | undefined);
|
|
130
|
+
}
|
|
131
|
+
declare class ParseError extends ScraperError {
|
|
132
|
+
readonly data?: any | undefined;
|
|
133
|
+
constructor(message: string, data?: any | undefined);
|
|
134
|
+
}
|
|
135
|
+
declare class RateLimitError extends ScraperError {
|
|
136
|
+
readonly retryAfter?: number | undefined;
|
|
137
|
+
constructor(message?: string, retryAfter?: number | undefined);
|
|
138
|
+
}
|
|
139
|
+
declare class TimeoutError extends ScraperError {
|
|
140
|
+
constructor(message?: string);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
declare function filterReviews(reviews: ParsedReview[], filters: FilterOptions): ParsedReview[];
|
|
144
|
+
declare function searchReviews(reviews: ParsedReview[], query: string): ParsedReview[];
|
|
145
|
+
|
|
146
|
+
declare function scrapeStream(url: string, options?: ScraperOptions): AsyncGenerator<ParsedReview | any, void, unknown>;
|
|
147
|
+
|
|
148
|
+
declare function scraper(url: string, options?: ScraperOptions): Promise<any>;
|
|
149
|
+
|
|
150
|
+
export { type BatchOptions, type BatchResult, type CacheOptions, FetchError, type FilterOptions, InvalidUrlError, ParseError, type ParsedReview, type ProgressCallback, RateLimitError, type RateLimitOptions, type RetryOptions, type ReviewAnalytics, type ReviewAuthor, type ReviewContent, type ReviewImage, type ReviewImageLocation, type ReviewImageSize, type ReviewResponse, type ReviewTime, ScraperError, type ScraperOptions, SortEnum, type SortType, TimeoutError, batchScraper, calculateAnalytics, filterReviews, getRecentReviews, getTopRatedReviews, groupByRating, scrapeStream, scraper, searchReviews };
|