@agentsean/crawler 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.
Files changed (70) hide show
  1. package/LICENSE +661 -0
  2. package/dist/adaptive.d.ts +9 -0
  3. package/dist/adaptive.d.ts.map +1 -0
  4. package/dist/adaptive.js +43 -0
  5. package/dist/adaptive.js.map +1 -0
  6. package/dist/crawl.d.ts +4 -0
  7. package/dist/crawl.d.ts.map +1 -0
  8. package/dist/crawl.js +348 -0
  9. package/dist/crawl.js.map +1 -0
  10. package/dist/decode.d.ts +7 -0
  11. package/dist/decode.d.ts.map +1 -0
  12. package/dist/decode.js +53 -0
  13. package/dist/decode.js.map +1 -0
  14. package/dist/extract.d.ts +4 -0
  15. package/dist/extract.d.ts.map +1 -0
  16. package/dist/extract.js +268 -0
  17. package/dist/extract.js.map +1 -0
  18. package/dist/hash.d.ts +4 -0
  19. package/dist/hash.d.ts.map +1 -0
  20. package/dist/hash.js +11 -0
  21. package/dist/hash.js.map +1 -0
  22. package/dist/http.d.ts +38 -0
  23. package/dist/http.d.ts.map +1 -0
  24. package/dist/http.js +207 -0
  25. package/dist/http.js.map +1 -0
  26. package/dist/index.d.ts +14 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +13 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/persist.d.ts +20 -0
  31. package/dist/persist.d.ts.map +1 -0
  32. package/dist/persist.js +186 -0
  33. package/dist/persist.js.map +1 -0
  34. package/dist/probe.d.ts +4 -0
  35. package/dist/probe.d.ts.map +1 -0
  36. package/dist/probe.js +132 -0
  37. package/dist/probe.js.map +1 -0
  38. package/dist/readability.d.ts +9 -0
  39. package/dist/readability.d.ts.map +1 -0
  40. package/dist/readability.js +60 -0
  41. package/dist/readability.js.map +1 -0
  42. package/dist/render.d.ts +15 -0
  43. package/dist/render.d.ts.map +1 -0
  44. package/dist/render.js +87 -0
  45. package/dist/render.js.map +1 -0
  46. package/dist/robots.d.ts +13 -0
  47. package/dist/robots.d.ts.map +1 -0
  48. package/dist/robots.js +187 -0
  49. package/dist/robots.js.map +1 -0
  50. package/dist/simhash.d.ts +9 -0
  51. package/dist/simhash.d.ts.map +1 -0
  52. package/dist/simhash.js +58 -0
  53. package/dist/simhash.js.map +1 -0
  54. package/dist/sitemap.d.ts +3 -0
  55. package/dist/sitemap.d.ts.map +1 -0
  56. package/dist/sitemap.js +165 -0
  57. package/dist/sitemap.js.map +1 -0
  58. package/dist/types.d.ts +251 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/ua.d.ts +3 -0
  63. package/dist/ua.d.ts.map +1 -0
  64. package/dist/ua.js +3 -0
  65. package/dist/ua.js.map +1 -0
  66. package/dist/url.d.ts +11 -0
  67. package/dist/url.d.ts.map +1 -0
  68. package/dist/url.js +114 -0
  69. package/dist/url.js.map +1 -0
  70. package/package.json +60 -0
package/dist/robots.js ADDED
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Vendored robots.txt matcher.
3
+ *
4
+ * `robots-parser` 3.0.1 last published 2023-02-21 (stale). We do not depend
5
+ * on it. This implements RFC 9309 matching (most-octets wins, allow wins ties)
6
+ * with Google-style group selection (single most-specific user-agent group,
7
+ * no merge across product tokens).
8
+ *
9
+ * Status handling (both modes are RFC 9309 compliant):
10
+ * - 4xx except 429 → allow-all (RFC §2.3.1.3)
11
+ * - 5xx / 429 / network → polite-crawl: disallow-all (RFC §2.3.1.4 MUST)
12
+ */
13
+ import { contentHash } from "./hash.js";
14
+ import { pathOf } from "./url.js";
15
+ const KNOWN = new Set(["user-agent", "allow", "disallow", "sitemap", "crawl-delay"]);
16
+ export function parseRobotsTxt(raw) {
17
+ const lines = raw.replace(/^\uFEFF/, "").split(/\r?\n/);
18
+ const groups = [];
19
+ const sitemaps = [];
20
+ const unknownDirectives = [];
21
+ let hasNoindexDirective = false;
22
+ let current = null;
23
+ let pendingAgents = [];
24
+ const flushAgents = () => {
25
+ if (pendingAgents.length === 0)
26
+ return;
27
+ current = { agents: pendingAgents, rules: [], crawlDelay: null };
28
+ groups.push(current);
29
+ pendingAgents = [];
30
+ };
31
+ for (const rawLine of lines) {
32
+ const line = rawLine.replace(/#.*$/, "").trim();
33
+ if (!line)
34
+ continue;
35
+ const colon = line.indexOf(":");
36
+ if (colon < 1) {
37
+ unknownDirectives.push(rawLine.trim());
38
+ continue;
39
+ }
40
+ const field = line.slice(0, colon).trim().toLowerCase();
41
+ const value = line.slice(colon + 1).trim();
42
+ if (field === "user-agent") {
43
+ if (current && current.rules.length + (current.crawlDelay ? 1 : 0) > 0) {
44
+ pendingAgents = [value.toLowerCase()];
45
+ current = null;
46
+ }
47
+ else if (pendingAgents.length > 0 && current === null) {
48
+ pendingAgents.push(value.toLowerCase());
49
+ }
50
+ else if (current && current.rules.length === 0 && !current.crawlDelay) {
51
+ current.agents.push(value.toLowerCase());
52
+ }
53
+ else {
54
+ pendingAgents = [value.toLowerCase()];
55
+ current = null;
56
+ }
57
+ continue;
58
+ }
59
+ if (field === "sitemap") {
60
+ sitemaps.push(value);
61
+ continue;
62
+ }
63
+ if (field === "noindex") {
64
+ hasNoindexDirective = true;
65
+ continue;
66
+ }
67
+ if (!KNOWN.has(field)) {
68
+ unknownDirectives.push(`${field}: ${value}`);
69
+ continue;
70
+ }
71
+ flushAgents();
72
+ if (!current) {
73
+ current = { agents: ["*"], rules: [], crawlDelay: null };
74
+ groups.push(current);
75
+ }
76
+ if (field === "allow") {
77
+ current.rules.push({ type: "allow", pattern: value });
78
+ }
79
+ else if (field === "disallow") {
80
+ current.rules.push({ type: "disallow", pattern: value });
81
+ }
82
+ else if (field === "crawl-delay") {
83
+ const n = Number(value);
84
+ current.crawlDelay = Number.isFinite(n) ? n : current.crawlDelay;
85
+ }
86
+ }
87
+ const hasCrawlDelay = groups.some((g) => g.crawlDelay !== null);
88
+ const crawlDelay = groups.find((g) => g.crawlDelay !== null)?.crawlDelay ?? null;
89
+ const disallowAll = groups.some((g) => (g.agents.includes("*") || g.agents.includes("googlebot")) &&
90
+ g.rules.some((r) => r.type === "disallow" && (r.pattern === "/" || r.pattern === "/*")));
91
+ return {
92
+ raw,
93
+ groups,
94
+ sitemaps,
95
+ unknownDirectives,
96
+ hasNoindexDirective,
97
+ hasCrawlDelay,
98
+ crawlDelay,
99
+ disallowAll,
100
+ hash: contentHash(raw),
101
+ };
102
+ }
103
+ export function robotsFromFetch(opts) {
104
+ const serverError = opts.error !== null ||
105
+ opts.statusCode === 429 ||
106
+ (opts.statusCode !== null && opts.statusCode >= 500);
107
+ if (serverError) {
108
+ const parsed = parseRobotsTxt(opts.raw || "");
109
+ return {
110
+ ...parsed,
111
+ ...opts,
112
+ mode: "disallow-all",
113
+ groups: parsed.groups,
114
+ };
115
+ }
116
+ if (opts.statusCode !== null && opts.statusCode >= 400 && opts.statusCode < 500) {
117
+ const parsed = parseRobotsTxt("");
118
+ return { ...parsed, ...opts, raw: opts.raw, mode: "allow-all" };
119
+ }
120
+ const parsed = parseRobotsTxt(opts.raw);
121
+ return { ...parsed, ...opts, mode: "parsed" };
122
+ }
123
+ export function isAllowedByRobots(robots, url, userAgent = "seanbot") {
124
+ if (robots.mode === "allow-all")
125
+ return true;
126
+ if (robots.mode === "disallow-all")
127
+ return false;
128
+ const path = pathOf(url);
129
+ const group = selectGroup(robots.groups, userAgent);
130
+ if (!group)
131
+ return true;
132
+ return mostSpecificAllows(group, path);
133
+ }
134
+ function selectGroup(groups, ua) {
135
+ const uaLower = ua.toLowerCase();
136
+ const matching = groups.filter((g) => g.agents.some((a) => a === "*" || uaLower.includes(a)));
137
+ const specific = matching.filter((g) => g.agents.some((a) => a !== "*"));
138
+ if (specific.length > 0) {
139
+ specific.sort((a, b) => longestAgent(b) - longestAgent(a));
140
+ return specific[0];
141
+ }
142
+ return matching.find((g) => g.agents.includes("*"));
143
+ }
144
+ function longestAgent(g) {
145
+ return Math.max(0, ...g.agents.map((a) => (a === "*" ? 0 : a.length)));
146
+ }
147
+ function mostSpecificAllows(group, path) {
148
+ let bestOctets = -1;
149
+ let allowed = true;
150
+ for (const rule of group.rules) {
151
+ if (!rule.pattern)
152
+ continue;
153
+ if (!matchRule(rule.pattern, path))
154
+ continue;
155
+ const octets = Buffer.byteLength(rule.pattern);
156
+ if (octets > bestOctets) {
157
+ bestOctets = octets;
158
+ allowed = rule.type === "allow";
159
+ }
160
+ else if (octets === bestOctets && rule.type === "allow") {
161
+ allowed = true;
162
+ }
163
+ }
164
+ return allowed;
165
+ }
166
+ export function matchRule(pattern, path) {
167
+ let end = false;
168
+ let p = pattern;
169
+ if (p.endsWith("$")) {
170
+ end = true;
171
+ p = p.slice(0, -1);
172
+ }
173
+ let re = "^";
174
+ for (const ch of p) {
175
+ if (ch === "*")
176
+ re += ".*";
177
+ else
178
+ re += escapeRe(ch);
179
+ }
180
+ if (end)
181
+ re += "$";
182
+ return new RegExp(re).test(path);
183
+ }
184
+ function escapeRe(ch) {
185
+ return ch.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
186
+ }
187
+ //# sourceMappingURL=robots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"robots.js","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 64-bit SimHash over character 3-grams. Near-duplicate when Hamming ≤ 3.
3
+ * Implemented in-process so we never take a Python/datasketch dependency.
4
+ */
5
+ export declare function simhash64(text: string): bigint;
6
+ export declare function simhashHex(text: string): string;
7
+ export declare function hamming64(a: bigint, b: bigint): number;
8
+ export declare function nearDuplicate(aHex: string, bHex: string, maxDistance?: number): boolean;
9
+ //# sourceMappingURL=simhash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simhash.d.ts","sourceRoot":"","sources":["../src/simhash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgB9C;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQtD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,SAAI,GAAG,OAAO,CAElF"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * 64-bit SimHash over character 3-grams. Near-duplicate when Hamming ≤ 3.
3
+ * Implemented in-process so we never take a Python/datasketch dependency.
4
+ */
5
+ export function simhash64(text) {
6
+ const tokens = shingles(text.toLowerCase(), 3);
7
+ if (tokens.length === 0)
8
+ return 0n;
9
+ const acc = new Int32Array(64);
10
+ for (const token of tokens) {
11
+ const h = fnv1a64(token);
12
+ for (let i = 0; i < 64; i++) {
13
+ const bit = (h >> BigInt(i)) & 1n;
14
+ acc[i] = (acc[i] ?? 0) + (bit === 1n ? 1 : -1);
15
+ }
16
+ }
17
+ let out = 0n;
18
+ for (let i = 0; i < 64; i++) {
19
+ if ((acc[i] ?? 0) >= 0)
20
+ out |= 1n << BigInt(i);
21
+ }
22
+ return out;
23
+ }
24
+ export function simhashHex(text) {
25
+ return simhash64(text).toString(16).padStart(16, "0");
26
+ }
27
+ export function hamming64(a, b) {
28
+ let x = a ^ b;
29
+ let n = 0;
30
+ while (x) {
31
+ x &= x - 1n;
32
+ n++;
33
+ }
34
+ return n;
35
+ }
36
+ export function nearDuplicate(aHex, bHex, maxDistance = 3) {
37
+ return hamming64(BigInt(`0x${aHex}`), BigInt(`0x${bHex}`)) <= maxDistance;
38
+ }
39
+ function shingles(text, n) {
40
+ const cleaned = text.replace(/\s+/g, " ").trim();
41
+ if (cleaned.length < n)
42
+ return cleaned ? [cleaned] : [];
43
+ const out = [];
44
+ for (let i = 0; i <= cleaned.length - n; i++) {
45
+ out.push(cleaned.slice(i, i + n));
46
+ }
47
+ return out;
48
+ }
49
+ function fnv1a64(str) {
50
+ let hash = 0xcbf29ce484222325n;
51
+ const prime = 0x100000001b3n;
52
+ for (let i = 0; i < str.length; i++) {
53
+ hash ^= BigInt(str.charCodeAt(i));
54
+ hash = (hash * prime) & 0xffffffffffffffffn;
55
+ }
56
+ return hash;
57
+ }
58
+ //# sourceMappingURL=simhash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simhash.js","sourceRoot":"","sources":["../src/simhash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ParsedSitemap } from "./types.js";
2
+ export declare function parseSitemapXml(raw: Buffer, sitemapUrl: string, gzipped: boolean): Promise<Omit<ParsedSitemap, "statusCode" | "contentType">>;
3
+ //# sourceMappingURL=sitemap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,YAAY,CAAC;AAK5D,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,GAAG,aAAa,CAAC,CAAC,CAa5D"}
@@ -0,0 +1,165 @@
1
+ import { SaxesParser } from "saxes";
2
+ import zlib from "node:zlib";
3
+ import { promisify } from "node:util";
4
+ import { absolutize } from "./url.js";
5
+ const gunzip = promisify(zlib.gunzip);
6
+ const NS = "http://www.sitemaps.org/schemas/sitemap/0.9";
7
+ export async function parseSitemapXml(raw, sitemapUrl, gzipped) {
8
+ let bytes = raw;
9
+ let gzipBroken = false;
10
+ if (gzipped || sitemapUrl.endsWith(".gz")) {
11
+ try {
12
+ bytes = await gunzip(raw);
13
+ }
14
+ catch {
15
+ gzipBroken = true;
16
+ return empty(sitemapUrl, "gzip_broken", gzipBroken, raw.length);
17
+ }
18
+ }
19
+ const xml = bytes.toString("utf8");
20
+ return parseXml(xml, sitemapUrl, bytes.length, gzipBroken);
21
+ }
22
+ function empty(url, error, gzipBroken, bytes) {
23
+ return {
24
+ url,
25
+ error,
26
+ bytes,
27
+ gzipBroken,
28
+ malformed: true,
29
+ namespace: null,
30
+ isIndex: false,
31
+ nestedIndex: false,
32
+ urls: [],
33
+ childSitemaps: [],
34
+ relativeLocs: [],
35
+ };
36
+ }
37
+ function parseXml(xml, sitemapUrl, bytes, gzipBroken) {
38
+ const parser = new SaxesParser({ xmlns: true, fragment: false });
39
+ const urls = [];
40
+ const childSitemaps = [];
41
+ const relativeLocs = [];
42
+ let namespace = null;
43
+ let isIndex = false;
44
+ let nestedIndex = false;
45
+ let malformed = false;
46
+ let error = null;
47
+ let path = [];
48
+ let text = "";
49
+ let current = null;
50
+ let videoFields = {};
51
+ parser.on("error", (e) => {
52
+ malformed = true;
53
+ error = e.message;
54
+ });
55
+ parser.on("opentag", (tag) => {
56
+ const local = tag.local ?? tag.name.replace(/^.*:/, "");
57
+ path.push(local.toLowerCase());
58
+ text = "";
59
+ if (local.toLowerCase() === "urlset") {
60
+ namespace = tag.uri || tag.attributes?.xmlns?.value || NS;
61
+ }
62
+ if (local.toLowerCase() === "sitemapindex") {
63
+ isIndex = true;
64
+ namespace = tag.uri || tag.attributes?.xmlns?.value || NS;
65
+ if (path.filter((p) => p === "sitemapindex").length > 1)
66
+ nestedIndex = true;
67
+ }
68
+ if (local.toLowerCase() === "url") {
69
+ current = { images: [], hreflang: [] };
70
+ videoFields = {};
71
+ }
72
+ });
73
+ parser.on("text", (t) => {
74
+ text += t;
75
+ });
76
+ parser.on("closetag", (tag) => {
77
+ const local = (tag.local ?? tag.name.replace(/^.*:/, "")).toLowerCase();
78
+ const value = text.trim();
79
+ if (current) {
80
+ if (local === "loc" && path[path.length - 2] === "url")
81
+ current.loc = value;
82
+ if (local === "lastmod")
83
+ current.lastmod = value;
84
+ if (local === "changefreq")
85
+ current.changefreq = value;
86
+ if (local === "priority")
87
+ current.priority = value;
88
+ if (local === "loc" && path.includes("image"))
89
+ current.images.push(value);
90
+ if (local === "link") {
91
+ /* xhtml:link handled via attributes in opentag — see below */
92
+ }
93
+ if (path.includes("video")) {
94
+ videoFields[local] = value;
95
+ }
96
+ if (local === "url") {
97
+ const loc = current.loc ?? "";
98
+ if (loc && !/^https?:\/\//i.test(loc))
99
+ relativeLocs.push(loc);
100
+ const videoValid = Object.keys(videoFields).length
101
+ ? Boolean(videoFields["thumbnail_loc"] &&
102
+ videoFields["title"] &&
103
+ videoFields["description"] &&
104
+ (videoFields["content_loc"] || videoFields["player_loc"]))
105
+ : null;
106
+ urls.push({
107
+ loc,
108
+ lastmod: current.lastmod ?? null,
109
+ changefreq: current.changefreq ?? null,
110
+ priority: current.priority ?? null,
111
+ images: current.images,
112
+ videoValid,
113
+ hreflang: current.hreflang,
114
+ });
115
+ current = null;
116
+ }
117
+ }
118
+ else if (isIndex && local === "loc") {
119
+ childSitemaps.push(value);
120
+ }
121
+ path.pop();
122
+ text = "";
123
+ });
124
+ // saxes xmlns attributes: capture xhtml:link hreflang on opentag via a second pass
125
+ const hrefLangRe = /<xhtml:link[^>]*rel=["']alternate["'][^>]*hreflang=["']([^"']+)["'][^>]*href=["']([^"']+)["'][^>]*\/?>/gi;
126
+ let hm;
127
+ const extras = [];
128
+ while ((hm = hrefLangRe.exec(xml))) {
129
+ extras.push({ lang: hm[1] ?? "", href: hm[2] ?? "" });
130
+ }
131
+ try {
132
+ parser.write(xml);
133
+ parser.close();
134
+ }
135
+ catch (e) {
136
+ malformed = true;
137
+ error = e instanceof Error ? e.message : "parse";
138
+ }
139
+ if (extras.length && urls.length) {
140
+ const first = urls[0];
141
+ if (first)
142
+ first.hreflang.push(...extras);
143
+ }
144
+ for (const u of urls) {
145
+ if (u.loc && !u.loc.startsWith("http")) {
146
+ const abs = absolutize(u.loc, sitemapUrl);
147
+ if (abs)
148
+ u.loc = abs;
149
+ }
150
+ }
151
+ return {
152
+ url: sitemapUrl,
153
+ error,
154
+ bytes,
155
+ gzipBroken,
156
+ malformed,
157
+ namespace,
158
+ isIndex,
159
+ nestedIndex,
160
+ urls,
161
+ childSitemaps,
162
+ relativeLocs,
163
+ };
164
+ }
165
+ //# sourceMappingURL=sitemap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sitemap.js","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":"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"}