Add optional cookie parameter to bypass bot detection (403 errors). Cookies can be provided via parameter, KIJIJI_COOKIE env var, or cookies/kijiji.json file. Supports both JSON array and string formats. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
import { fetchKijijiItems } from "@marketplace-scrapers/core";
|
|
|
|
/**
|
|
* GET /api/kijiji?q={query}
|
|
* Search Kijiji marketplace for listings
|
|
*/
|
|
export async function kijijiRoute(req: Request): Promise<Response> {
|
|
const reqUrl = new URL(req.url);
|
|
|
|
const SEARCH_QUERY =
|
|
req.headers.get("query") || reqUrl.searchParams.get("q") || null;
|
|
if (!SEARCH_QUERY)
|
|
return Response.json(
|
|
{
|
|
message: "Request didn't have 'query' header or 'q' search parameter!",
|
|
},
|
|
{ status: 400 },
|
|
);
|
|
|
|
const maxPagesParam = reqUrl.searchParams.get("maxPages");
|
|
const maxPages = maxPagesParam ? parseInt(maxPagesParam, 10) : 5;
|
|
const priceMinParam = reqUrl.searchParams.get("priceMin");
|
|
const priceMin = priceMinParam ? parseInt(priceMinParam, 10) : undefined;
|
|
const priceMaxParam = reqUrl.searchParams.get("priceMax");
|
|
const priceMax = priceMaxParam ? parseInt(priceMaxParam, 10) : undefined;
|
|
|
|
const searchOptions = {
|
|
location: reqUrl.searchParams.get("location") || undefined,
|
|
category: reqUrl.searchParams.get("category") || undefined,
|
|
keywords: reqUrl.searchParams.get("keywords") || undefined,
|
|
sortBy: reqUrl.searchParams.get("sortBy") as
|
|
| "relevancy"
|
|
| "date"
|
|
| "price"
|
|
| "distance"
|
|
| undefined,
|
|
sortOrder: reqUrl.searchParams.get("sortOrder") as
|
|
| "desc"
|
|
| "asc"
|
|
| undefined,
|
|
maxPages,
|
|
priceMin,
|
|
priceMax,
|
|
cookies: reqUrl.searchParams.get("cookies") || undefined,
|
|
};
|
|
|
|
try {
|
|
const items = await fetchKijijiItems(
|
|
SEARCH_QUERY,
|
|
4, // 4 requests per second for faster scraping
|
|
"https://www.kijiji.ca",
|
|
searchOptions,
|
|
{},
|
|
);
|
|
if (!items)
|
|
return Response.json(
|
|
{ message: "Search didn't return any results!" },
|
|
{ status: 404 },
|
|
);
|
|
return Response.json(items, { status: 200 });
|
|
} catch (error) {
|
|
console.error("Kijiji scraping error:", error);
|
|
const errorMessage =
|
|
error instanceof Error ? error.message : "Unknown error occurred";
|
|
return Response.json({ message: errorMessage }, { status: 400 });
|
|
}
|
|
}
|