mcp-scraper 0.32.0 → 0.32.1
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/README.md +1 -1
- package/dist/bin/api-server.cjs +47 -28
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +1 -1
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/{chunk-YOOEAXWP.js → chunk-2FY4VBAY.js} +2 -2
- package/dist/chunk-VJBS6RPB.js +7 -0
- package/dist/chunk-VJBS6RPB.js.map +1 -0
- package/dist/{server-OBOTNFD6.js → server-GXTYKIAX.js} +49 -30
- package/dist/{server-OBOTNFD6.js.map → server-GXTYKIAX.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-CPQF3PYW.js +0 -7
- package/dist/chunk-CPQF3PYW.js.map +0 -1
- /package/dist/{chunk-YOOEAXWP.js.map → chunk-2FY4VBAY.js.map} +0 -0
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
registerMemoryMcpTools,
|
|
8
8
|
registerPaaExtractorMcpTools,
|
|
9
9
|
registerSerpIntelligenceCaptureTools
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-2FY4VBAY.js";
|
|
11
11
|
import "../chunk-R7EETU7Z.js";
|
|
12
12
|
import "../chunk-MTSBI7ZH.js";
|
|
13
13
|
import {
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
import "../chunk-PTHY7NYD.js";
|
|
17
17
|
import {
|
|
18
18
|
PACKAGE_VERSION
|
|
19
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-VJBS6RPB.js";
|
|
20
20
|
import "../chunk-4767BA2O.js";
|
|
21
21
|
import "../chunk-M2S27J6Z.js";
|
|
22
22
|
import "../chunk-ICT7DDHL.js";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "./chunk-PTHY7NYD.js";
|
|
20
20
|
import {
|
|
21
21
|
PACKAGE_VERSION
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-VJBS6RPB.js";
|
|
23
23
|
import {
|
|
24
24
|
MC_PER_CREDIT
|
|
25
25
|
} from "./chunk-4767BA2O.js";
|
|
@@ -10110,4 +10110,4 @@ export {
|
|
|
10110
10110
|
MEMORY_TOOL_SCHEMAS,
|
|
10111
10111
|
registerMemoryMcpTools
|
|
10112
10112
|
};
|
|
10113
|
-
//# sourceMappingURL=chunk-
|
|
10113
|
+
//# sourceMappingURL=chunk-2FY4VBAY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const PACKAGE_VERSION = '0.32.1'\n"],"mappings":";AAAO,IAAM,kBAAkB;","names":[]}
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
sanitizeAttempts,
|
|
37
37
|
sanitizeHarvestResult,
|
|
38
38
|
transcribeMediaUrl
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-2FY4VBAY.js";
|
|
40
40
|
import {
|
|
41
41
|
auditImages,
|
|
42
42
|
buildLinkReport,
|
|
@@ -77,7 +77,7 @@ import {
|
|
|
77
77
|
RawMapsOverviewSchema,
|
|
78
78
|
RawMapsReviewStatsSchema
|
|
79
79
|
} from "./chunk-PTHY7NYD.js";
|
|
80
|
-
import "./chunk-
|
|
80
|
+
import "./chunk-VJBS6RPB.js";
|
|
81
81
|
import {
|
|
82
82
|
completeExtractJob,
|
|
83
83
|
countSuccessfulPages,
|
|
@@ -13205,29 +13205,38 @@ var MapsSearchExtractor = class {
|
|
|
13205
13205
|
};
|
|
13206
13206
|
const phonePattern = /(?:\+?1[\s.-]?)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}/;
|
|
13207
13207
|
const addressPattern = /\b[A-Z]{2}\s+\d{5}(?:-\d{4})?\b|\b(?:St|Street|Ave|Avenue|Rd|Road|Blvd|Boulevard|Dr|Drive|Ln|Lane|Way|Pkwy|Parkway)\b/i;
|
|
13208
|
-
const
|
|
13209
|
-
const
|
|
13210
|
-
return Boolean(
|
|
13208
|
+
const headings = Array.from(document.querySelectorAll('div[role="heading"]')).filter((heading) => {
|
|
13209
|
+
const text2 = normalize(heading.textContent);
|
|
13210
|
+
return Boolean(text2) && !/^(?:businesses|places|sponsored|people also ask|discussions and forums|more businesses|more places|custom date range|choose what you)/i.test(text2 ?? "");
|
|
13211
13211
|
});
|
|
13212
13212
|
const seen = /* @__PURE__ */ new Set();
|
|
13213
13213
|
const out = [];
|
|
13214
|
-
|
|
13215
|
-
|
|
13214
|
+
let cardIndex = -1;
|
|
13215
|
+
for (const heading of headings) {
|
|
13216
|
+
let card = heading;
|
|
13217
|
+
for (let hop = 0; hop < 8; hop++) {
|
|
13218
|
+
const parent = card.parentElement;
|
|
13219
|
+
if (!parent || parent.querySelectorAll('div[role="heading"]').length > 1) break;
|
|
13220
|
+
card = parent;
|
|
13221
|
+
}
|
|
13222
|
+
if (card.closest('[role="dialog"], dialog')) continue;
|
|
13223
|
+
const name = normalize(heading.textContent);
|
|
13216
13224
|
if (!name) continue;
|
|
13217
|
-
const
|
|
13218
|
-
|
|
13225
|
+
const lines = (card.innerText ?? "").split("\n").map((line) => normalize(line)).filter((line) => Boolean(line));
|
|
13226
|
+
if (/^sponsored$/i.test(lines[0] ?? "")) continue;
|
|
13227
|
+
const ratingLine = lines.find((line) => /\d(?:\.\d)?\s*\(/.test(line)) ?? "";
|
|
13228
|
+
const rating = ratingLine.match(/(\d(?:\.\d)?)\s*\(/)?.[1] ?? null;
|
|
13229
|
+
const reviewCount = ratingLine.match(/\((\d[\d,]*)\)/)?.[1]?.replace(/,/g, "") ?? null;
|
|
13230
|
+
const category = normalize(ratingLine.split("\xB7").slice(1).join("\xB7"));
|
|
13231
|
+
const phone = lines.map((line) => line.match(phonePattern)?.[0]).find((value) => Boolean(value)) ?? null;
|
|
13232
|
+
const hoursStatus = normalize((lines.find((line) => /\b(?:open|closed|opens|closes)\b/i.test(line)) ?? "").split("\xB7")[0] ?? "");
|
|
13233
|
+
const address = lines.find((line) => addressPattern.test(line)) ?? null;
|
|
13234
|
+
const websiteUrl = Array.from(card.querySelectorAll("a[href]")).map((anchor) => anchor.href).find((href) => /^https?:/i.test(href) && !/google\.|gstatic|googleusercontent/.test(href)) ?? null;
|
|
13235
|
+
if (!rating && !(phone && websiteUrl)) continue;
|
|
13236
|
+
const key = `${name.toLowerCase()}|${lines.join(" ").toLowerCase()}`;
|
|
13219
13237
|
if (seen.has(key)) continue;
|
|
13220
13238
|
seen.add(key);
|
|
13221
|
-
|
|
13222
|
-
const aria = normalize(card.getAttribute("aria-label"));
|
|
13223
|
-
const rating = (aria ?? text2).match(/(?:rated\s+)?(\d(?:\.\d)?)\s*(?:out of 5)?/i)?.[1] ?? null;
|
|
13224
|
-
const reviewCount = (aria ?? text2).match(/(?:\(|·\s*)([\d,]+)\s+(?:user\s+)?reviews?\b/i)?.[1]?.replace(/,/g, "") ?? null;
|
|
13225
|
-
const phone = lines.find((line) => phonePattern.test(line)) ?? null;
|
|
13226
|
-
const address = lines.find((line) => addressPattern.test(line)) ?? null;
|
|
13227
|
-
const hoursStatus = lines.find((line) => /\b(?:open|closed|opens|closes)\b/i.test(line)) ?? null;
|
|
13228
|
-
const category = lines.find(
|
|
13229
|
-
(line) => line !== name && line !== phone && line !== address && line !== hoursStatus && !/^(?:rated|\d[\d.,]*\s*(?:out of 5|reviews?)?)\b/i.test(line) && !/sponsored|website|directions|call|save|share|more/i.test(line)
|
|
13230
|
-
) ?? null;
|
|
13239
|
+
cardIndex += 1;
|
|
13231
13240
|
const mapsSearchUrl = `https://www.google.com/maps/search/${encodeURIComponent([name, locationHint].filter(Boolean).join(" "))}`;
|
|
13232
13241
|
out.push({
|
|
13233
13242
|
cardIndex,
|
|
@@ -13242,7 +13251,7 @@ var MapsSearchExtractor = class {
|
|
|
13242
13251
|
address,
|
|
13243
13252
|
phone,
|
|
13244
13253
|
hoursStatus,
|
|
13245
|
-
websiteUrl
|
|
13254
|
+
websiteUrl,
|
|
13246
13255
|
directionsUrl: `https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent([name, address].filter(Boolean).join(", "))}`,
|
|
13247
13256
|
metadata: lines.slice(0, 20)
|
|
13248
13257
|
});
|
|
@@ -13251,17 +13260,27 @@ var MapsSearchExtractor = class {
|
|
|
13251
13260
|
}, fallbackLocation);
|
|
13252
13261
|
}
|
|
13253
13262
|
async openCardAndExtractDialog(page, card, includeServices) {
|
|
13263
|
+
if (!includeServices) return null;
|
|
13254
13264
|
const clicked = await page.evaluate((input) => {
|
|
13255
13265
|
const normalize = (value) => (value ?? "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
13256
|
-
const
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
13263
|
-
|
|
13264
|
-
|
|
13266
|
+
const headings = Array.from(document.querySelectorAll('div[role="heading"]'));
|
|
13267
|
+
for (const heading of headings) {
|
|
13268
|
+
let target = heading;
|
|
13269
|
+
for (let hop = 0; hop < 8; hop++) {
|
|
13270
|
+
const parent = target.parentElement;
|
|
13271
|
+
if (!parent || parent.querySelectorAll('div[role="heading"]').length > 1) break;
|
|
13272
|
+
target = parent;
|
|
13273
|
+
}
|
|
13274
|
+
if (target.closest('[role="dialog"], dialog')) continue;
|
|
13275
|
+
const name = normalize(heading.textContent);
|
|
13276
|
+
if (!name) continue;
|
|
13277
|
+
const lines = (target.innerText ?? "").split("\n").map((line) => normalize(line)).filter(Boolean);
|
|
13278
|
+
if (`${name}|${lines.join(" ")}` !== input.cardKey) continue;
|
|
13279
|
+
target.click();
|
|
13280
|
+
return true;
|
|
13281
|
+
}
|
|
13282
|
+
return false;
|
|
13283
|
+
}, { cardKey: card.cardKey });
|
|
13265
13284
|
if (!clicked) return null;
|
|
13266
13285
|
const dialog = page.locator('dialog, [role="dialog"]').filter({ has: page.locator('h1, h2, [role="heading"]') }).last();
|
|
13267
13286
|
await dialog.waitFor({ state: "visible", timeout: 6e3 }).catch(() => {
|
|
@@ -27608,4 +27627,4 @@ app.get("/blog/:slug/", (c) => {
|
|
|
27608
27627
|
export {
|
|
27609
27628
|
app
|
|
27610
27629
|
};
|
|
27611
|
-
//# sourceMappingURL=server-
|
|
27630
|
+
//# sourceMappingURL=server-GXTYKIAX.js.map
|