You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chajia/scripts/probe-priority1-quote-extra...

119 lines
4.2 KiB

import { randomUUID } from "node:crypto";
import { mkdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { chromium } from "playwright";
const ENTRY =
"https://www.priority1.com/instant-freight-quotes/#New%20Step%201";
const CLICK = { noWaitAfter: true as const };
async function typeField(
page: import("playwright").Page,
sel: string,
value: string,
) {
const loc = page.locator(`#container-mh ${sel}`).first();
await loc.click(CLICK);
await loc.fill("");
await loc.pressSequentially(value, { delay: 20 });
}
async function main() {
const out = join(process.cwd(), ".rpa", "priority1-probe-quotes");
mkdirSync(out, { recursive: true });
const network: Array<{ url: string; status: number; body: string }> = [];
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
page.on("response", async (res) => {
const url = res.url();
if (!/quote|rate|pricing|ltl|feathery|priority/i.test(url)) return;
if (!res.headers()["content-type"]?.includes("json")) return;
try {
const body = await res.text();
if (body.length > 50) {
network.push({ url, status: res.status(), body: body.slice(0, 8000) });
}
} catch {
/* ignore */
}
});
await page.goto(ENTRY, { waitUntil: "domcontentloaded" });
await page.locator("#container-mh").waitFor();
await page.waitForTimeout(1500);
await page.locator("#cb_st_ltl").click({ force: true, ...CLICK });
await page
.locator("#container-mh")
.getByText(/^Less Than Truckload/i)
.first()
.click(CLICK)
.catch(() => undefined);
await page.waitForTimeout(600);
await typeField(page, "#origin-zip", "10118");
await typeField(page, "#destination-zip", "90017");
await page.locator("#container-mh #freight-shipment").selectOption("One Time Shipment");
await typeField(page, "#pickup-date", "07/01/2026");
await typeField(page, "#business-email", "niqijiti542@gmail.com");
await typeField(page, "#client-phone", "2125550198");
const btn1 = page
.locator("#container-mh")
.getByRole("button", { name: /GET INSTANT QUOTES/i })
.first();
await btn1.click(CLICK);
await page.locator("#container-mh #length").waitFor({ state: "visible", timeout: 60_000 });
await typeField(page, "#length", "48");
await typeField(page, "#width", "40");
await typeField(page, "#height", "48");
await typeField(page, "#weight", "30");
await typeField(page, "#number-of-pallets", "2");
const pkg = page
.locator("#container-mh select")
.filter({ has: page.locator('option:has-text("Pallet")') });
if ((await pkg.count()) > 0) await pkg.first().selectOption("Pallet");
await page.locator("#container-mh #PickupLocation").selectOption("Residence / Home Business");
await page.locator("#container-mh #DropoffLocation").selectOption("Residence / Home Business");
const btn2 = page
.locator("#container-mh")
.getByRole("button", { name: /GET INSTANT QUOTES/i })
.first();
await btn2.click(CLICK);
const started = Date.now();
while (Date.now() - started < 90_000) {
const has = await page.evaluate(() => /\$[\d,]+\.\d{2}/.test(document.body.innerText));
if (has) break;
await page.waitForTimeout(2000);
}
const dom = await page.evaluate(() => {
const cards = [...document.querySelectorAll("#container-mh *")].filter((el) => {
const t = el.textContent || "";
return /\$[\d,]+\.\d{2}/.test(t) && t.length < 500;
});
return cards.slice(0, 15).map((el) => ({
tag: el.tagName,
class: (el as HTMLElement).className?.slice?.(0, 80),
text: el.textContent?.replace(/\s+/g, " ").trim().slice(0, 200),
}));
});
writeFileSync(join(out, "network.json"), JSON.stringify(network, null, 2));
writeFileSync(join(out, "dom.json"), JSON.stringify(dom, null, 2));
await page.screenshot({ path: join(out, "quote.png"), fullPage: true });
console.log("network:", network.length, "dom cards:", dom.length);
console.log("out:", out);
for (const n of network.slice(0, 5)) {
console.log("---", n.url, n.status);
console.log(n.body.slice(0, 500));
}
console.log("dom sample:", JSON.stringify(dom.slice(0, 5), null, 2));
await browser.close();
}
main().catch(console.error);