@crawlee/utils 3.0.0-alpha.2 → 3.0.0-alpha.3
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/dist/LICENSE.md +201 -0
- package/{README.md → dist/README.md} +0 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/{index.js → dist/index.js} +0 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +18 -0
- package/dist/internals/cheerio.d.ts +32 -0
- package/dist/internals/cheerio.d.ts.map +1 -0
- package/dist/internals/cheerio.js +94 -0
- package/dist/internals/cheerio.js.map +1 -0
- package/dist/internals/extract-urls.d.ts +39 -0
- package/dist/internals/extract-urls.d.ts.map +1 -0
- package/dist/internals/extract-urls.js +41 -0
- package/dist/internals/extract-urls.js.map +1 -0
- package/dist/internals/general.d.ts +62 -0
- package/dist/internals/general.d.ts.map +1 -0
- package/dist/internals/general.js +143 -0
- package/dist/internals/general.js.map +1 -0
- package/dist/internals/memory-info.d.ts +26 -0
- package/dist/internals/memory-info.d.ts.map +1 -0
- package/dist/internals/memory-info.js +142 -0
- package/dist/internals/memory-info.js.map +1 -0
- package/dist/internals/social.d.ts +493 -0
- package/dist/internals/social.d.ts.map +1 -0
- package/dist/internals/social.js +661 -0
- package/dist/internals/social.js.map +1 -0
- package/dist/internals/typedefs.d.ts +11 -0
- package/dist/internals/typedefs.d.ts.map +1 -0
- package/dist/internals/typedefs.js +15 -0
- package/dist/internals/typedefs.js.map +1 -0
- package/dist/package.json +58 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +9 -8
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseContentTypeFromResponse = exports.purgeLocalStorage = exports.snakeCaseToCamelCase = exports.sleep = exports.weightedAvg = exports.isDocker = exports.URL_WITH_COMMAS_REGEX = exports.URL_NO_COMMAS_REGEX = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const consts_1 = require("@apify/consts");
|
|
6
|
+
const content_type_1 = tslib_1.__importDefault(require("content-type"));
|
|
7
|
+
const mime_types_1 = tslib_1.__importDefault(require("mime-types"));
|
|
8
|
+
const promises_1 = tslib_1.__importDefault(require("node:fs/promises"));
|
|
9
|
+
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
10
|
+
const promises_2 = require("node:timers/promises");
|
|
11
|
+
const node_url_1 = require("node:url");
|
|
12
|
+
const ow_1 = tslib_1.__importDefault(require("ow"));
|
|
13
|
+
/**
|
|
14
|
+
* Default regular expression to match URLs in a string that may be plain text, JSON, CSV or other. It supports common URL characters
|
|
15
|
+
* and does not support URLs containing commas or spaces. The URLs also may contain Unicode letters (not symbols).
|
|
16
|
+
*/
|
|
17
|
+
exports.URL_NO_COMMAS_REGEX = RegExp('https?://(www\\.)?[\\p{L}0-9][-\\p{L}0-9@:%._\\+~#=]{0,254}[\\p{L}0-9]\\.[a-z]{2,63}(:\\d{1,5})?(/[-\\p{L}0-9@:%_\\+.~#?&//=\\(\\)]*)?', 'giu'); // eslint-disable-line
|
|
18
|
+
/**
|
|
19
|
+
* Regular expression that, in addition to the default regular expression `URL_NO_COMMAS_REGEX`, supports matching commas in URL path and query.
|
|
20
|
+
* Note, however, that this may prevent parsing URLs from comma delimited lists, or the URLs may become malformed.
|
|
21
|
+
*/
|
|
22
|
+
exports.URL_WITH_COMMAS_REGEX = RegExp('https?://(www\\.)?[\\p{L}0-9][-\\p{L}0-9@:%._\\+~#=]{0,254}[\\p{L}0-9]\\.[a-z]{2,63}(:\\d{1,5})?(/[-\\p{L}0-9@:%_\\+,.~#?&//=\\(\\)]*)?', 'giu'); // eslint-disable-line
|
|
23
|
+
let isDockerPromiseCache;
|
|
24
|
+
async function createIsDockerPromise() {
|
|
25
|
+
const promise1 = promises_1.default.stat('/.dockerenv')
|
|
26
|
+
.then(() => true)
|
|
27
|
+
.catch(() => false);
|
|
28
|
+
const promise2 = promises_1.default.readFile('/proc/self/cgroup', 'utf8')
|
|
29
|
+
.then((content) => content.includes('docker'))
|
|
30
|
+
.catch(() => false);
|
|
31
|
+
const [result1, result2] = await Promise.all([promise1, promise2]);
|
|
32
|
+
return result1 || result2;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns a `Promise` that resolves to true if the code is running in a Docker container.
|
|
36
|
+
*/
|
|
37
|
+
function isDocker(forceReset) {
|
|
38
|
+
// Parameter forceReset is just internal for unit tests.
|
|
39
|
+
if (!isDockerPromiseCache || forceReset)
|
|
40
|
+
isDockerPromiseCache = createIsDockerPromise();
|
|
41
|
+
return isDockerPromiseCache;
|
|
42
|
+
}
|
|
43
|
+
exports.isDocker = isDocker;
|
|
44
|
+
/**
|
|
45
|
+
* Computes a weighted average of an array of numbers, complemented by an array of weights.
|
|
46
|
+
* @ignore
|
|
47
|
+
*/
|
|
48
|
+
function weightedAvg(arrValues, arrWeights) {
|
|
49
|
+
const result = arrValues.map((value, i) => {
|
|
50
|
+
const weight = arrWeights[i];
|
|
51
|
+
const sum = value * weight;
|
|
52
|
+
return [sum, weight];
|
|
53
|
+
}).reduce((p, c) => [p[0] + c[0], p[1] + c[1]], [0, 0]);
|
|
54
|
+
return result[0] / result[1];
|
|
55
|
+
}
|
|
56
|
+
exports.weightedAvg = weightedAvg;
|
|
57
|
+
/**
|
|
58
|
+
* Returns a `Promise` that resolves after a specific period of time. This is useful to implement waiting
|
|
59
|
+
* in your code, e.g. to prevent overloading of target website or to avoid bot detection.
|
|
60
|
+
*
|
|
61
|
+
* **Example usage:**
|
|
62
|
+
*
|
|
63
|
+
* ```
|
|
64
|
+
* const { sleep } = require('@crawlee/utils');
|
|
65
|
+
*
|
|
66
|
+
* ...
|
|
67
|
+
*
|
|
68
|
+
* // Sleep 1.5 seconds
|
|
69
|
+
* await sleep(1500);
|
|
70
|
+
* ```
|
|
71
|
+
* @param millis Period of time to sleep, in milliseconds. If not a positive number, the returned promise resolves immediately.
|
|
72
|
+
*/
|
|
73
|
+
function sleep(millis) {
|
|
74
|
+
return (0, promises_2.setTimeout)(millis);
|
|
75
|
+
}
|
|
76
|
+
exports.sleep = sleep;
|
|
77
|
+
/**
|
|
78
|
+
* Converts SNAKE_CASE to camelCase.
|
|
79
|
+
* @ignore
|
|
80
|
+
*/
|
|
81
|
+
function snakeCaseToCamelCase(snakeCaseStr) {
|
|
82
|
+
return snakeCaseStr
|
|
83
|
+
.toLowerCase()
|
|
84
|
+
.split('_')
|
|
85
|
+
.map((part, index) => {
|
|
86
|
+
return index > 0
|
|
87
|
+
? part.charAt(0).toUpperCase() + part.slice(1)
|
|
88
|
+
: part;
|
|
89
|
+
})
|
|
90
|
+
.join('');
|
|
91
|
+
}
|
|
92
|
+
exports.snakeCaseToCamelCase = snakeCaseToCamelCase;
|
|
93
|
+
/**
|
|
94
|
+
* Cleans up the local storage folder created when testing locally.
|
|
95
|
+
* This is useful in the event you are debugging your code locally.
|
|
96
|
+
*
|
|
97
|
+
* Be careful as this will remove the folder you provide and everything in it!
|
|
98
|
+
*
|
|
99
|
+
* @param [folder] The folder to clean up
|
|
100
|
+
*/
|
|
101
|
+
async function purgeLocalStorage(folder) {
|
|
102
|
+
// If the user did not provide a folder, try to get it from the env variables, or the default one
|
|
103
|
+
if (!folder) {
|
|
104
|
+
folder = process.env[consts_1.ENV_VARS.LOCAL_STORAGE_DIR] || 'apify_storage';
|
|
105
|
+
}
|
|
106
|
+
// Clear the folder
|
|
107
|
+
await promises_1.default.rm(folder, { recursive: true, force: true });
|
|
108
|
+
}
|
|
109
|
+
exports.purgeLocalStorage = purgeLocalStorage;
|
|
110
|
+
/**
|
|
111
|
+
* Gets parsed content type from response object
|
|
112
|
+
* @param response HTTP response object
|
|
113
|
+
* @ignore
|
|
114
|
+
*/
|
|
115
|
+
function parseContentTypeFromResponse(response) {
|
|
116
|
+
(0, ow_1.default)(response, ow_1.default.object.partialShape({
|
|
117
|
+
url: ow_1.default.string.url,
|
|
118
|
+
headers: ow_1.default.object,
|
|
119
|
+
}));
|
|
120
|
+
const { url, headers } = response;
|
|
121
|
+
let parsedContentType;
|
|
122
|
+
if (headers['content-type']) {
|
|
123
|
+
try {
|
|
124
|
+
parsedContentType = content_type_1.default.parse(headers['content-type']);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Can not parse content type from Content-Type header. Try to parse it from file extension.
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Parse content type from file extension as fallback
|
|
131
|
+
if (!parsedContentType) {
|
|
132
|
+
const parsedUrl = new node_url_1.URL(url);
|
|
133
|
+
const contentTypeFromExtname = mime_types_1.default.contentType(node_path_1.default.extname(parsedUrl.pathname))
|
|
134
|
+
|| 'application/octet-stream; charset=utf-8'; // Fallback content type, specified in https://tools.ietf.org/html/rfc7231#section-3.1.1.5
|
|
135
|
+
parsedContentType = content_type_1.default.parse(contentTypeFromExtname);
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
type: parsedContentType.type,
|
|
139
|
+
charset: parsedContentType.parameters.charset,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
exports.parseContentTypeFromResponse = parseContentTypeFromResponse;
|
|
143
|
+
//# sourceMappingURL=general.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"general.js","sourceRoot":"","sources":["../../src/internals/general.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Describes memory usage of the process.
|
|
3
|
+
*/
|
|
4
|
+
export interface MemoryInfo {
|
|
5
|
+
/** Total memory available in the system or container */
|
|
6
|
+
totalBytes: number;
|
|
7
|
+
/** Amount of free memory in the system or container */
|
|
8
|
+
freeBytes: number;
|
|
9
|
+
/** Amount of memory used (= totalBytes - freeBytes) */
|
|
10
|
+
usedBytes: number;
|
|
11
|
+
/** Amount of memory used the current Node.js process */
|
|
12
|
+
mainProcessBytes: number;
|
|
13
|
+
/** Amount of memory used by child processes of the current Node.js process */
|
|
14
|
+
childProcessesBytes: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Returns memory statistics of the process and the system, see {@link MemoryInfo}.
|
|
18
|
+
*
|
|
19
|
+
* If the process runs inside of Docker, the `getMemoryInfo` gets container memory limits,
|
|
20
|
+
* otherwise it gets system memory limits.
|
|
21
|
+
*
|
|
22
|
+
* Beware that the function is quite inefficient because it spawns a new process.
|
|
23
|
+
* Therefore you shouldn't call it too often, like more than once per second.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getMemoryInfo(): Promise<MemoryInfo>;
|
|
26
|
+
//# sourceMappingURL=memory-info.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-info.d.ts","sourceRoot":"","sources":["../../src/internals/memory-info.ts"],"names":[],"mappings":"AAqBA;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IAEnB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAElB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAElB,wDAAwD;IACxD,gBAAgB,EAAE,MAAM,CAAC;IAEzB,8EAA8E;IAC9E,mBAAmB,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAmHzD"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMemoryInfo = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const log_1 = tslib_1.__importDefault(require("@apify/log"));
|
|
6
|
+
// @ts-expect-error We need to add typings for @apify/ps-tree
|
|
7
|
+
const ps_tree_1 = tslib_1.__importDefault(require("@apify/ps-tree"));
|
|
8
|
+
const node_child_process_1 = require("node:child_process");
|
|
9
|
+
const promises_1 = tslib_1.__importDefault(require("node:fs/promises"));
|
|
10
|
+
const node_os_1 = tslib_1.__importDefault(require("node:os"));
|
|
11
|
+
const node_util_1 = tslib_1.__importDefault(require("node:util"));
|
|
12
|
+
const general_1 = require("./general");
|
|
13
|
+
const MEMORY_FILE_PATHS = {
|
|
14
|
+
TOTAL: {
|
|
15
|
+
V1: '/sys/fs/cgroup/memory/memory.limit_in_bytes',
|
|
16
|
+
V2: '/sys/fs/cgroup/memory.max',
|
|
17
|
+
},
|
|
18
|
+
USED: {
|
|
19
|
+
V1: '/sys/fs/cgroup/memory/memory.usage_in_bytes',
|
|
20
|
+
V2: '/sys/fs/cgroup/memory.current',
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Returns memory statistics of the process and the system, see {@link MemoryInfo}.
|
|
25
|
+
*
|
|
26
|
+
* If the process runs inside of Docker, the `getMemoryInfo` gets container memory limits,
|
|
27
|
+
* otherwise it gets system memory limits.
|
|
28
|
+
*
|
|
29
|
+
* Beware that the function is quite inefficient because it spawns a new process.
|
|
30
|
+
* Therefore you shouldn't call it too often, like more than once per second.
|
|
31
|
+
*/
|
|
32
|
+
async function getMemoryInfo() {
|
|
33
|
+
const psTreePromised = node_util_1.default.promisify(ps_tree_1.default);
|
|
34
|
+
// lambda does *not* have `ps` and other command line tools
|
|
35
|
+
// required to extract memory usage.
|
|
36
|
+
const isLambdaEnvironment = process.platform === 'linux'
|
|
37
|
+
&& !!process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE;
|
|
38
|
+
const isDockerVar = !isLambdaEnvironment && await (0, general_1.isDocker)();
|
|
39
|
+
let mainProcessBytes = -1;
|
|
40
|
+
let childProcessesBytes = 0;
|
|
41
|
+
if (isLambdaEnvironment) {
|
|
42
|
+
// reported in bytes
|
|
43
|
+
mainProcessBytes = process.memoryUsage().rss;
|
|
44
|
+
// TODO this is quite ugly, let's introduce some local variables
|
|
45
|
+
// https://stackoverflow.com/a/55914335/129415
|
|
46
|
+
childProcessesBytes = +(0, node_child_process_1.execSync)('cat /proc/meminfo')
|
|
47
|
+
.toString()
|
|
48
|
+
.split(/[\n: ]/)
|
|
49
|
+
.filter((val) => val.trim())[19]
|
|
50
|
+
* 1000 // meminfo reports in kb, not bytes
|
|
51
|
+
// the total used memory is reported by meminfo
|
|
52
|
+
// subtract memory used by the main node process
|
|
53
|
+
// in order to infer memory used by any child processes
|
|
54
|
+
- mainProcessBytes;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// Query both root and child processes
|
|
58
|
+
const processes = await psTreePromised(process.pid, true);
|
|
59
|
+
processes.forEach((rec) => {
|
|
60
|
+
// Skip the 'ps' or 'wmic' commands used by ps-tree to query the processes
|
|
61
|
+
if (rec.COMMAND === 'ps' || rec.COMMAND === 'WMIC.exe') {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const bytes = parseInt(rec.RSS, 10);
|
|
65
|
+
// Obtain main process' memory separately
|
|
66
|
+
if (rec.PID === `${process.pid}`) {
|
|
67
|
+
mainProcessBytes = bytes;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
childProcessesBytes += bytes;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
let totalBytes;
|
|
74
|
+
let usedBytes;
|
|
75
|
+
let freeBytes;
|
|
76
|
+
if (isLambdaEnvironment) {
|
|
77
|
+
// memory size is defined in megabytes
|
|
78
|
+
totalBytes = parseInt(process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE, 10) * 1000000;
|
|
79
|
+
usedBytes = mainProcessBytes + childProcessesBytes;
|
|
80
|
+
freeBytes = totalBytes - usedBytes;
|
|
81
|
+
log_1.default.debug(`lambda size of ${totalBytes} with ${freeBytes} free bytes`);
|
|
82
|
+
}
|
|
83
|
+
else if (isDockerVar) {
|
|
84
|
+
// When running inside Docker container, use container memory limits
|
|
85
|
+
// Check whether cgroups V1 or V2 is used
|
|
86
|
+
let cgroupsVersion = 'V1';
|
|
87
|
+
try {
|
|
88
|
+
// If this directory does not exists, assume docker is using cgroups V2
|
|
89
|
+
await promises_1.default.access('/sys/fs/cgroup/memory/');
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
cgroupsVersion = 'V2';
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
let [totalBytesStr, usedBytesStr] = await Promise.all([
|
|
96
|
+
promises_1.default.readFile(MEMORY_FILE_PATHS.TOTAL[cgroupsVersion], 'utf8'),
|
|
97
|
+
promises_1.default.readFile(MEMORY_FILE_PATHS.USED[cgroupsVersion], 'utf8'),
|
|
98
|
+
]);
|
|
99
|
+
// Cgroups V2 files contains newline character. Getting rid of it for better handling in later part of the code.
|
|
100
|
+
totalBytesStr = totalBytesStr.replace(/[^a-zA-Z0-9 ]/g, '');
|
|
101
|
+
usedBytesStr = usedBytesStr.replace(/[^a-zA-Z0-9 ]/g, '');
|
|
102
|
+
// Cgroups V2 contains 'max' string if memory is not limited
|
|
103
|
+
// See https://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git/tree/Documentation/admin-guide/cgroup-v2.rst (see "memory.max")
|
|
104
|
+
if (totalBytesStr === 'max') {
|
|
105
|
+
totalBytes = node_os_1.default.totalmem();
|
|
106
|
+
// Cgroups V1 is set to number related to platform and page size if memory is not limited
|
|
107
|
+
// See https://unix.stackexchange.com/q/420906
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
totalBytes = parseInt(totalBytesStr, 10);
|
|
111
|
+
const containerRunsWithUnlimitedMemory = totalBytes > Number.MAX_SAFE_INTEGER;
|
|
112
|
+
if (containerRunsWithUnlimitedMemory)
|
|
113
|
+
totalBytes = node_os_1.default.totalmem();
|
|
114
|
+
}
|
|
115
|
+
usedBytes = parseInt(usedBytesStr, 10);
|
|
116
|
+
freeBytes = totalBytes - usedBytes;
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
// log.deprecated logs a warning only once
|
|
120
|
+
log_1.default.deprecated('Your environment is Docker, but your system does not support memory cgroups. '
|
|
121
|
+
+ 'If you\'re running containers with limited memory, memory auto-scaling will not work properly.\n\n'
|
|
122
|
+
+ `Cause: ${err.message}`);
|
|
123
|
+
totalBytes = node_os_1.default.totalmem();
|
|
124
|
+
freeBytes = node_os_1.default.freemem();
|
|
125
|
+
usedBytes = totalBytes - freeBytes;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
totalBytes = node_os_1.default.totalmem();
|
|
130
|
+
freeBytes = node_os_1.default.freemem();
|
|
131
|
+
usedBytes = totalBytes - freeBytes;
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
totalBytes,
|
|
135
|
+
freeBytes,
|
|
136
|
+
usedBytes,
|
|
137
|
+
mainProcessBytes,
|
|
138
|
+
childProcessesBytes,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
exports.getMemoryInfo = getMemoryInfo;
|
|
142
|
+
//# sourceMappingURL=memory-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-info.js","sourceRoot":"","sources":["../../src/internals/memory-info.ts"],"names":[],"mappings":"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"}
|