fix(bikegear): preserve listing referrer for paged and detail requests
This commit is contained in:
parent
57b174bb3c
commit
b460853806
@ -6,6 +6,7 @@ const { chromium } = require("playwright");
|
|||||||
|
|
||||||
const DEFAULT_URL = "https://bikegear.in/acerbis";
|
const DEFAULT_URL = "https://bikegear.in/acerbis";
|
||||||
const TEST_URL = process.argv[2] || process.env.BIKEGEAR_PROXY_TEST_URL || DEFAULT_URL;
|
const TEST_URL = process.argv[2] || process.env.BIKEGEAR_PROXY_TEST_URL || DEFAULT_URL;
|
||||||
|
const WARM_URL = process.env.BIKEGEAR_PROXY_TEST_WARM_URL || DEFAULT_URL;
|
||||||
const PROFILE_PATH = path.resolve("data/sources/bikegear/.browser-profile-test");
|
const PROFILE_PATH = path.resolve("data/sources/bikegear/.browser-profile-test");
|
||||||
|
|
||||||
const STEALTH_SCRIPT = `
|
const STEALTH_SCRIPT = `
|
||||||
@ -100,6 +101,7 @@ async function main() {
|
|||||||
await fs.mkdir(PROFILE_PATH, { recursive: true });
|
await fs.mkdir(PROFILE_PATH, { recursive: true });
|
||||||
|
|
||||||
console.log(`[BIKEGEAR-PROXY-TEST] url=${TEST_URL}`);
|
console.log(`[BIKEGEAR-PROXY-TEST] url=${TEST_URL}`);
|
||||||
|
console.log(`[BIKEGEAR-PROXY-TEST] warmUrl=${TEST_URL === WARM_URL ? "-" : WARM_URL}`);
|
||||||
console.log(`[BIKEGEAR-PROXY-TEST] proxy=${maskProxyUrl(proxyUrl)}`);
|
console.log(`[BIKEGEAR-PROXY-TEST] proxy=${maskProxyUrl(proxyUrl)}`);
|
||||||
|
|
||||||
const context = await chromium.launchPersistentContext(PROFILE_PATH, {
|
const context = await chromium.launchPersistentContext(PROFILE_PATH, {
|
||||||
@ -119,7 +121,18 @@ async function main() {
|
|||||||
try {
|
try {
|
||||||
await context.addInitScript(STEALTH_SCRIPT);
|
await context.addInitScript(STEALTH_SCRIPT);
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
const response = await page.goto(TEST_URL, { waitUntil: "domcontentloaded", timeout: 45000 });
|
|
||||||
|
if (TEST_URL !== WARM_URL) {
|
||||||
|
const warmResponse = await page.goto(WARM_URL, { waitUntil: "domcontentloaded", timeout: 45000 });
|
||||||
|
await page.waitForTimeout(8000);
|
||||||
|
console.log(`[BIKEGEAR-PROXY-TEST] warmStatus=${warmResponse?.status() || 0}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await page.goto(TEST_URL, {
|
||||||
|
waitUntil: "domcontentloaded",
|
||||||
|
timeout: 45000,
|
||||||
|
...(TEST_URL !== WARM_URL ? { referer: WARM_URL } : {}),
|
||||||
|
});
|
||||||
await page.waitForTimeout(8000);
|
await page.waitForTimeout(8000);
|
||||||
|
|
||||||
const status = response?.status() || 0;
|
const status = response?.status() || 0;
|
||||||
|
|||||||
@ -180,19 +180,23 @@ async function recycleBrowserContext() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchHtmlWithBrowserQueued(url) {
|
async function fetchHtmlWithBrowserQueued(url, referer = null) {
|
||||||
const run = _browserFetchQueue.then(() => fetchHtmlWithBrowser(url));
|
const run = _browserFetchQueue.then(() => fetchHtmlWithBrowser(url, referer));
|
||||||
_browserFetchQueue = run.catch(() => {});
|
_browserFetchQueue = run.catch(() => {});
|
||||||
return run;
|
return run;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchHtmlWithBrowser(url) {
|
async function fetchHtmlWithBrowser(url, referer = null) {
|
||||||
const context = await getBrowserContext();
|
const context = await getBrowserContext();
|
||||||
|
|
||||||
for (let attempt = 1; attempt <= 5; attempt += 1) {
|
for (let attempt = 1; attempt <= 5; attempt += 1) {
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
try {
|
try {
|
||||||
const response = await page.goto(url, { waitUntil: "domcontentloaded", timeout: 45000 });
|
const response = await page.goto(url, {
|
||||||
|
waitUntil: "domcontentloaded",
|
||||||
|
timeout: 45000,
|
||||||
|
...(referer ? { referer } : {}),
|
||||||
|
});
|
||||||
const status = response?.status() ?? 0;
|
const status = response?.status() ?? 0;
|
||||||
|
|
||||||
if (status === 429 || status >= 500) {
|
if (status === 429 || status >= 500) {
|
||||||
@ -284,9 +288,9 @@ function sleep(ms) {
|
|||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchHtml(url, attempt = 1) {
|
function fetchHtml(url, attempt = 1, referer = null) {
|
||||||
return FETCH_MODE === "browser"
|
return FETCH_MODE === "browser"
|
||||||
? fetchHtmlWithBrowserQueued(url)
|
? fetchHtmlWithBrowserQueued(url, referer)
|
||||||
: fetchHtmlWithHttp(url, attempt);
|
: fetchHtmlWithHttp(url, attempt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +352,7 @@ async function scrapeBrandProductUrls(brand) {
|
|||||||
await runConcurrent(pageNums, async (pageNum) => {
|
await runConcurrent(pageNums, async (pageNum) => {
|
||||||
const pageUrl = `${brand.url}?page=${pageNum}`;
|
const pageUrl = `${brand.url}?page=${pageNum}`;
|
||||||
try {
|
try {
|
||||||
const pageHtml = await fetchHtml(pageUrl);
|
const pageHtml = await fetchHtml(pageUrl, 1, brand.url);
|
||||||
for (const u of extractProductUrls(pageHtml)) urls.add(u);
|
for (const u of extractProductUrls(pageHtml)) urls.add(u);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn(`[BIKEGEAR][${brand.name}] Failed page ${pageNum}: ${err.message}`);
|
console.warn(`[BIKEGEAR][${brand.name}] Failed page ${pageNum}: ${err.message}`);
|
||||||
@ -463,10 +467,10 @@ function parsePrice(str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Scrape a single product detail page and return structured data. */
|
/** Scrape a single product detail page and return structured data. */
|
||||||
async function scrapeProductDetail(productUrl, brandName) {
|
async function scrapeProductDetail(productUrl, brandName, refererUrl = null) {
|
||||||
let html;
|
let html;
|
||||||
try {
|
try {
|
||||||
html = await fetchHtml(productUrl);
|
html = await fetchHtml(productUrl, 1, refererUrl);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return { url: productUrl, scrapeError: err.message };
|
return { url: productUrl, scrapeError: err.message };
|
||||||
}
|
}
|
||||||
@ -520,7 +524,7 @@ async function scrapeBikeGear() {
|
|||||||
|
|
||||||
let done = 0;
|
let done = 0;
|
||||||
const products = await runConcurrent(productUrls, async (url) => {
|
const products = await runConcurrent(productUrls, async (url) => {
|
||||||
const product = await scrapeProductDetail(url, brand.name);
|
const product = await scrapeProductDetail(url, brand.name, brand.url);
|
||||||
done++;
|
done++;
|
||||||
if (product.scrapeError) {
|
if (product.scrapeError) {
|
||||||
console.warn(`[BIKEGEAR][${brand.name}] ${done}/${productUrls.length} ERR ${url}: ${product.scrapeError}`);
|
console.warn(`[BIKEGEAR][${brand.name}] ${done}/${productUrls.length} ERR ${url}: ${product.scrapeError}`);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user