@crawlee/impit-client 4.0.0-beta.18 → 4.0.0-beta.181
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 +14 -14
- package/index.d.ts +16 -30
- package/index.js +70 -75
- package/package.json +7 -11
- package/index.d.ts.map +0 -1
- package/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
<h1 align="center">
|
|
2
2
|
<a href="https://crawlee.dev">
|
|
3
3
|
<picture>
|
|
4
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-dark.svg?sanitize=true"
|
|
5
|
-
<img alt="Crawlee" src="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-light.svg?sanitize=true" width="500"
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-dark.svg?sanitize=true" />
|
|
5
|
+
<img alt="Crawlee" src="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-light.svg?sanitize=true" width="500" />
|
|
6
6
|
</picture>
|
|
7
7
|
</a>
|
|
8
|
-
<br
|
|
8
|
+
<br />
|
|
9
9
|
<small>A web scraping and browser automation library</small>
|
|
10
10
|
</h1>
|
|
11
11
|
|
|
12
|
-
<p align=center>
|
|
13
|
-
<a href="https://trendshift.io/repositories/5179" target="_blank"><img src="https://trendshift.io/api/badge/repositories/5179" alt="apify%2Fcrawlee | Trendshift"
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://trendshift.io/repositories/5179" target="_blank"><img src="https://trendshift.io/api/badge/repositories/5179" alt="apify%2Fcrawlee | Trendshift" width="250" height="55"/></a>
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
|
-
<p align=center>
|
|
17
|
-
<a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/v/@crawlee/core.svg" alt="NPM latest version" data-canonical-src="https://img.shields.io/npm/v/@crawlee/core/next.svg"
|
|
18
|
-
<a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/dm/@crawlee/core.svg" alt="Downloads" data-canonical-src="https://img.shields.io/npm/dm/@crawlee/core.svg"
|
|
19
|
-
<a href="https://discord.gg/jyEM2PRvMU" rel="nofollow"><img src="https://img.shields.io/discord/801163717915574323?label=discord" alt="Chat on discord" data-canonical-src="https://img.shields.io/discord/801163717915574323?label=discord"
|
|
20
|
-
<a href="https://github.com/apify/crawlee/actions/workflows/test-ci.yml"><img src="https://github.com/apify/crawlee/actions/workflows/test-ci.yml/badge.svg?branch=master" alt="Build Status"
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/v/@crawlee/core.svg" alt="NPM latest version" data-canonical-src="https://img.shields.io/npm/v/@crawlee/core/next.svg" /></a>
|
|
18
|
+
<a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/dm/@crawlee/core.svg" alt="Downloads" data-canonical-src="https://img.shields.io/npm/dm/@crawlee/core.svg" /></a>
|
|
19
|
+
<a href="https://discord.gg/jyEM2PRvMU" rel="nofollow"><img src="https://img.shields.io/discord/801163717915574323?label=discord" alt="Chat on discord" data-canonical-src="https://img.shields.io/discord/801163717915574323?label=discord" /></a>
|
|
20
|
+
<a href="https://github.com/apify/crawlee/actions/workflows/test-ci.yml"><img src="https://github.com/apify/crawlee/actions/workflows/test-ci.yml/badge.svg?branch=master" alt="Build Status" /></a>
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
23
|
Crawlee covers your crawling and scraping end-to-end and **helps you build reliable scrapers. Fast.**
|
|
@@ -89,7 +89,7 @@ By default, Crawlee stores data to `./storage` in the current working directory.
|
|
|
89
89
|
We provide automated beta builds for every merged code change in Crawlee. You can find them in the npm [list of releases](https://www.npmjs.com/package/crawlee?activeTab=versions). If you want to test new features or bug fixes before we release them, feel free to install a beta build like this:
|
|
90
90
|
|
|
91
91
|
```bash
|
|
92
|
-
npm install crawlee@
|
|
92
|
+
npm install crawlee@next
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
If you also use the [Apify SDK](https://github.com/apify/apify-sdk-js), you need to specify dependency overrides in your `package.json` file so that you don't end up with multiple versions of Crawlee installed:
|
|
@@ -98,9 +98,9 @@ If you also use the [Apify SDK](https://github.com/apify/apify-sdk-js), you need
|
|
|
98
98
|
{
|
|
99
99
|
"overrides": {
|
|
100
100
|
"apify": {
|
|
101
|
-
"@crawlee/core": "
|
|
102
|
-
"@crawlee/types": "
|
|
103
|
-
"@crawlee/utils": "
|
|
101
|
+
"@crawlee/core": "$crawlee",
|
|
102
|
+
"@crawlee/types": "$crawlee",
|
|
103
|
+
"@crawlee/utils": "$crawlee"
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
}
|
package/index.d.ts
CHANGED
|
@@ -1,41 +1,27 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
1
|
+
import type { CustomFetchOptions } from '@crawlee/http-client';
|
|
2
|
+
import { BaseHttpClient } from '@crawlee/http-client';
|
|
3
|
+
import type { CrawleeLogger } from '@crawlee/types';
|
|
4
|
+
import { type ImpitOptions } from 'impit';
|
|
3
5
|
export declare const Browser: {
|
|
4
|
-
readonly Chrome:
|
|
5
|
-
readonly Firefox:
|
|
6
|
+
readonly Chrome: 'chrome';
|
|
7
|
+
readonly Firefox: 'firefox';
|
|
6
8
|
};
|
|
7
9
|
/**
|
|
8
|
-
* A HTTP client implementation based on the `impit library.
|
|
10
|
+
* A HTTP client implementation based on the `impit` library.
|
|
9
11
|
*/
|
|
10
|
-
export declare class ImpitHttpClient
|
|
11
|
-
private
|
|
12
|
-
private maxRedirects;
|
|
13
|
-
private followRedirects;
|
|
14
|
-
/**
|
|
15
|
-
* Enables reuse of `impit` clients for the same set of options.
|
|
16
|
-
* This is useful for performance reasons, as creating
|
|
17
|
-
* a new client for each request breaks TCP connection
|
|
18
|
-
* (and other resources) reuse.
|
|
19
|
-
*/
|
|
20
|
-
private clientCache;
|
|
12
|
+
export declare class ImpitHttpClient extends BaseHttpClient {
|
|
13
|
+
#private;
|
|
21
14
|
private getClient;
|
|
22
|
-
constructor(options?: Omit<ImpitOptions, 'proxyUrl'> & {
|
|
23
|
-
maxRedirects?: number;
|
|
24
|
-
});
|
|
25
15
|
/**
|
|
26
|
-
*
|
|
27
|
-
* @param request `HttpRequest` object
|
|
28
|
-
* @returns `HttpResponse` object
|
|
16
|
+
* @param options.cacheClients Whether to cache `impit` clients between requests. Defaults to `true`.
|
|
29
17
|
*/
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
sendRequest(request: Request, options?: SendRequestOptions): Promise<Response>;
|
|
35
|
-
private getStreamWithProgress;
|
|
18
|
+
constructor(options?: Omit<ImpitOptions, 'proxyUrl' | 'timeout'> & {
|
|
19
|
+
cacheClients?: boolean;
|
|
20
|
+
logger?: CrawleeLogger;
|
|
21
|
+
});
|
|
36
22
|
/**
|
|
37
23
|
* @inheritDoc
|
|
38
24
|
*/
|
|
39
|
-
|
|
25
|
+
fetch(request: Request, options?: RequestInit & CustomFetchOptions): Promise<Response>;
|
|
26
|
+
private resolveImpitBrowser;
|
|
40
27
|
}
|
|
41
|
-
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -1,108 +1,103 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ResponseWithUrl } from '@crawlee/core';
|
|
1
|
+
import { BaseHttpClient, ResponseWithUrl } from '@crawlee/http-client';
|
|
3
2
|
import { Impit } from 'impit';
|
|
4
3
|
import { LruCache } from '@apify/datastructures';
|
|
4
|
+
// Concrete impit impersonation profiles per browser family. The plain `chrome` /
|
|
5
|
+
// `firefox` aliases fall back to the oldest available version, which is a
|
|
6
|
+
// fingerprint giveaway — we pick one of these explicitly instead. Keep in sync
|
|
7
|
+
// with impit's `Browser` type when bumping the dependency.
|
|
8
|
+
const IMPIT_VERSIONS_BY_BROWSER = {
|
|
9
|
+
chrome: [
|
|
10
|
+
'chrome100',
|
|
11
|
+
'chrome101',
|
|
12
|
+
'chrome104',
|
|
13
|
+
'chrome107',
|
|
14
|
+
'chrome110',
|
|
15
|
+
'chrome116',
|
|
16
|
+
'chrome124',
|
|
17
|
+
'chrome125',
|
|
18
|
+
'chrome131',
|
|
19
|
+
'chrome136',
|
|
20
|
+
'chrome142',
|
|
21
|
+
],
|
|
22
|
+
firefox: ['firefox128', 'firefox133', 'firefox135', 'firefox144'],
|
|
23
|
+
};
|
|
5
24
|
export const Browser = {
|
|
6
25
|
'Chrome': 'chrome',
|
|
7
26
|
'Firefox': 'firefox',
|
|
8
27
|
};
|
|
9
28
|
/**
|
|
10
|
-
* A HTTP client implementation based on the `impit library.
|
|
29
|
+
* A HTTP client implementation based on the `impit` library.
|
|
11
30
|
*/
|
|
12
|
-
export class ImpitHttpClient {
|
|
13
|
-
impitOptions;
|
|
14
|
-
|
|
15
|
-
followRedirects;
|
|
31
|
+
export class ImpitHttpClient extends BaseHttpClient {
|
|
32
|
+
#impitOptions;
|
|
33
|
+
#cacheClients;
|
|
16
34
|
/**
|
|
17
35
|
* Enables reuse of `impit` clients for the same set of options.
|
|
18
36
|
* This is useful for performance reasons, as creating
|
|
19
37
|
* a new client for each request breaks TCP connection
|
|
20
38
|
* (and other resources) reuse.
|
|
21
39
|
*/
|
|
22
|
-
clientCache = new LruCache({ maxLength: 10 });
|
|
40
|
+
#clientCache = new LruCache({ maxLength: 10 });
|
|
41
|
+
/**
|
|
42
|
+
* Stable impit impersonation version per fingerprint object, so the same
|
|
43
|
+
* session keeps impersonating the same browser version across requests
|
|
44
|
+
* instead of rerolling on every call.
|
|
45
|
+
*/
|
|
46
|
+
#impitBrowserByFingerprint = new WeakMap();
|
|
23
47
|
getClient(options) {
|
|
48
|
+
if (!this.#cacheClients) {
|
|
49
|
+
return new Impit(options);
|
|
50
|
+
}
|
|
24
51
|
const { cookieJar, ...rest } = options;
|
|
25
52
|
const cacheKey = JSON.stringify(rest);
|
|
26
|
-
const existingClient = this
|
|
53
|
+
const existingClient = this.#clientCache.get(cacheKey);
|
|
27
54
|
if (existingClient && (!cookieJar || existingClient.cookieJar === cookieJar)) {
|
|
28
55
|
return existingClient.client;
|
|
29
56
|
}
|
|
30
57
|
const client = new Impit(options);
|
|
31
|
-
this
|
|
58
|
+
this.#clientCache.add(cacheKey, { client, cookieJar: cookieJar });
|
|
32
59
|
return client;
|
|
33
60
|
}
|
|
34
|
-
constructor(options) {
|
|
35
|
-
this.impitOptions = options ?? {};
|
|
36
|
-
this.maxRedirects = options?.maxRedirects ?? 10;
|
|
37
|
-
this.followRedirects = options?.followRedirects ?? true;
|
|
38
|
-
}
|
|
39
61
|
/**
|
|
40
|
-
*
|
|
41
|
-
* @param request `HttpRequest` object
|
|
42
|
-
* @returns `HttpResponse` object
|
|
62
|
+
* @param options.cacheClients Whether to cache `impit` clients between requests. Defaults to `true`.
|
|
43
63
|
*/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
...this.impitOptions,
|
|
50
|
-
...(options?.cookieJar ? { cookieJar: options?.cookieJar } : {}),
|
|
51
|
-
proxyUrl: options?.session?.proxyInfo?.url,
|
|
52
|
-
followRedirects: false,
|
|
53
|
-
});
|
|
54
|
-
const response = await impit.fetch(request, { timeout: options?.timeout });
|
|
55
|
-
if (this.followRedirects && response.status >= 300 && response.status < 400) {
|
|
56
|
-
const location = response.headers.get('location');
|
|
57
|
-
const redirectUrl = new URL(location ?? '', request.url);
|
|
58
|
-
if (!location) {
|
|
59
|
-
throw new Error('Redirect response missing location header.');
|
|
60
|
-
}
|
|
61
|
-
return this.getResponse({
|
|
62
|
-
...request,
|
|
63
|
-
url: redirectUrl.href,
|
|
64
|
-
}, {
|
|
65
|
-
redirectCount: (redirects?.redirectCount ?? 0) + 1,
|
|
66
|
-
redirectUrls: [...(redirects?.redirectUrls ?? []), redirectUrl],
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
return {
|
|
70
|
-
response,
|
|
71
|
-
redirectUrls: redirects?.redirectUrls ?? [],
|
|
72
|
-
};
|
|
64
|
+
constructor(options) {
|
|
65
|
+
super({ logger: options?.logger });
|
|
66
|
+
const { cacheClients = true, logger: _logger, ...impitOptions } = options ?? {};
|
|
67
|
+
this.#impitOptions = impitOptions;
|
|
68
|
+
this.#cacheClients = cacheClients;
|
|
73
69
|
}
|
|
74
70
|
/**
|
|
75
71
|
* @inheritDoc
|
|
76
72
|
*/
|
|
77
|
-
async
|
|
78
|
-
const {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
73
|
+
async fetch(request, options) {
|
|
74
|
+
const { proxyUrl, redirect, signal, fingerprint, ignoreTlsErrors } = options ?? {};
|
|
75
|
+
const impitBrowser = this.resolveImpitBrowser(fingerprint);
|
|
76
|
+
const impit = this.getClient({
|
|
77
|
+
...this.#impitOptions,
|
|
78
|
+
...(impitBrowser ? { browser: impitBrowser } : {}),
|
|
79
|
+
// The per-request flag (from the crawler option or a MITM proxy session)
|
|
80
|
+
// can only enable ignoring, never override a constructor-level `true`.
|
|
81
|
+
...(ignoreTlsErrors ? { ignoreTlsErrors: true } : {}),
|
|
82
|
+
proxyUrl,
|
|
83
|
+
followRedirects: redirect === 'follow',
|
|
88
84
|
});
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
transferred,
|
|
93
|
-
total,
|
|
94
|
-
};
|
|
95
|
-
};
|
|
96
|
-
return [responseStream, getDownloadProgress];
|
|
85
|
+
const response = await impit.fetch(request, { signal: signal ?? undefined });
|
|
86
|
+
// todo - cast shouldn't be needed here, impit returns `Uint8Array`
|
|
87
|
+
return new ResponseWithUrl(response.body, response);
|
|
97
88
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
//
|
|
105
|
-
|
|
89
|
+
resolveImpitBrowser(fingerprint) {
|
|
90
|
+
if (!fingerprint?.browser)
|
|
91
|
+
return undefined;
|
|
92
|
+
const cached = this.#impitBrowserByFingerprint.get(fingerprint);
|
|
93
|
+
if (cached)
|
|
94
|
+
return cached;
|
|
95
|
+
// impit can only impersonate Chrome and Firefox. Map other (Chromium-based or
|
|
96
|
+
// unsupported) families like `edge`/`safari` onto Chrome so the request still
|
|
97
|
+
// carries realistic browser headers instead of impit's bare `*/*` defaults.
|
|
98
|
+
const versions = IMPIT_VERSIONS_BY_BROWSER[fingerprint.browser] ?? IMPIT_VERSIONS_BY_BROWSER.chrome;
|
|
99
|
+
const picked = versions[Math.floor(Math.random() * versions.length)];
|
|
100
|
+
this.#impitBrowserByFingerprint.set(fingerprint, picked);
|
|
101
|
+
return picked;
|
|
106
102
|
}
|
|
107
103
|
}
|
|
108
|
-
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crawlee/impit-client",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.181",
|
|
4
4
|
"description": "impit-based HTTP client implementation for Crawlee. Impersonates browser requests to avoid bot detection.",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"homepage": "https://crawlee.dev",
|
|
40
40
|
"scripts": {
|
|
41
|
-
"build": "
|
|
41
|
+
"build": "pnpm clean && pnpm compile && pnpm copy",
|
|
42
42
|
"clean": "rimraf ./dist",
|
|
43
43
|
"compile": "tsc -p tsconfig.build.json",
|
|
44
44
|
"copy": "tsx ../../scripts/copy.ts"
|
|
@@ -46,15 +46,11 @@
|
|
|
46
46
|
"publishConfig": {
|
|
47
47
|
"access": "public"
|
|
48
48
|
},
|
|
49
|
-
"peerDependencies": {
|
|
50
|
-
"@crawlee/core": "4.0.0"
|
|
51
|
-
},
|
|
52
|
-
"devDependencies": {
|
|
53
|
-
"@crawlee/core": "4.0.0"
|
|
54
|
-
},
|
|
55
49
|
"dependencies": {
|
|
56
|
-
"@apify/datastructures": "^
|
|
57
|
-
"
|
|
50
|
+
"@apify/datastructures": "^3.0.1",
|
|
51
|
+
"@crawlee/http-client": "4.0.0-beta.181",
|
|
52
|
+
"@crawlee/types": "4.0.0-beta.181",
|
|
53
|
+
"impit": "^0.14.2",
|
|
58
54
|
"tough-cookie": "^6.0.0"
|
|
59
55
|
},
|
|
60
56
|
"lerna": {
|
|
@@ -64,5 +60,5 @@
|
|
|
64
60
|
}
|
|
65
61
|
}
|
|
66
62
|
},
|
|
67
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "9ed15c042e37591cc2ee96f7e86d5472fece32eb"
|
|
68
64
|
}
|
package/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEvF,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,OAAO,CAAC;AAMzD,eAAO,MAAM,OAAO;;;CAGV,CAAC;AAOX;;GAEG;AACH,qBAAa,eAAgB,YAAW,cAAc;IAClD,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAU;IAEjC;;;;;OAKG;IACH,OAAO,CAAC,WAAW,CAA2F;IAE9G,OAAO,CAAC,SAAS;gBAgBL,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE;IAOhF;;;;OAIG;YACW,WAAW;IA+CzB;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAOpF,OAAO,CAAC,qBAAqB;IAqB7B;;OAEG;IACG,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC;CAO7E"}
|
package/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|