yandex-smartcaptcha-solver 1.0.0 → 1.0.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/index.js +55 -25
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -3,6 +3,7 @@ const { v4: uuidv4 } = require('uuid');
|
|
|
3
3
|
const FormData = require('form-data');
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
|
+
const { SocksProxyAgent } = require('socks-proxy-agent');
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Yandex SmartCaptcha Solver
|
|
@@ -51,7 +52,7 @@ class YandexSmartCaptchaSolver {
|
|
|
51
52
|
siteUrl: config.siteUrl,
|
|
52
53
|
siteKey: config.siteKey,
|
|
53
54
|
host: url.hostname,
|
|
54
|
-
coreName: config.coreName || null,
|
|
55
|
+
coreName: config.coreName || null,
|
|
55
56
|
|
|
56
57
|
// Опции
|
|
57
58
|
userAgent: options.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
@@ -68,7 +69,17 @@ class YandexSmartCaptchaSolver {
|
|
|
68
69
|
recognizedText: null
|
|
69
70
|
};
|
|
70
71
|
|
|
71
|
-
this.
|
|
72
|
+
if (this.config.saveImages && !fs.existsSync(this.config.imagesDir)) {
|
|
73
|
+
fs.mkdirSync(this.config.imagesDir, { recursive: true });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Создать axios инстанс с опциональным прокси
|
|
79
|
+
* @private
|
|
80
|
+
*/
|
|
81
|
+
_createAxiosInstance(proxy = null) {
|
|
82
|
+
const axiosConfig = {
|
|
72
83
|
headers: {
|
|
73
84
|
'User-Agent': this.config.userAgent,
|
|
74
85
|
'Accept': '*/*',
|
|
@@ -76,11 +87,22 @@ class YandexSmartCaptchaSolver {
|
|
|
76
87
|
'Accept-Encoding': 'gzip, deflate, br'
|
|
77
88
|
},
|
|
78
89
|
timeout: this.config.timeout
|
|
79
|
-
}
|
|
90
|
+
};
|
|
80
91
|
|
|
81
|
-
|
|
82
|
-
|
|
92
|
+
// Добавляем прокси агент, если указан
|
|
93
|
+
if (proxy) {
|
|
94
|
+
const proxyUrl = proxy.username && proxy.password
|
|
95
|
+
? `socks5://${proxy.username}:${proxy.password}@${proxy.host}:${proxy.port}`
|
|
96
|
+
: `socks5://${proxy.host}:${proxy.port}`;
|
|
97
|
+
|
|
98
|
+
const proxyAgent = new SocksProxyAgent(proxyUrl);
|
|
99
|
+
axiosConfig.httpAgent = proxyAgent;
|
|
100
|
+
axiosConfig.httpsAgent = proxyAgent;
|
|
101
|
+
|
|
102
|
+
this._log(`Using SOCKS5 proxy: ${proxy.host}:${proxy.port}`, 'info');
|
|
83
103
|
}
|
|
104
|
+
|
|
105
|
+
return axios.create(axiosConfig);
|
|
84
106
|
}
|
|
85
107
|
|
|
86
108
|
/**
|
|
@@ -146,7 +168,7 @@ class YandexSmartCaptchaSolver {
|
|
|
146
168
|
* Первый запрос к Yandex SmartCaptcha
|
|
147
169
|
* @private
|
|
148
170
|
*/
|
|
149
|
-
async _firstCheck() {
|
|
171
|
+
async _firstCheck(axiosInstance) {
|
|
150
172
|
this._log('Performing first check request...', 'debug');
|
|
151
173
|
|
|
152
174
|
const url = `https://smartcaptcha.yandexcloud.net/check?host=${this.config.host}&sitekey=${this.config.siteKey}&href=${encodeURIComponent(this.config.siteUrl)}`;
|
|
@@ -161,7 +183,7 @@ class YandexSmartCaptchaSolver {
|
|
|
161
183
|
'Sec-Fetch-Site': 'same-origin'
|
|
162
184
|
};
|
|
163
185
|
|
|
164
|
-
const response = await
|
|
186
|
+
const response = await axiosInstance.post(url, data, { headers });
|
|
165
187
|
return response.data;
|
|
166
188
|
}
|
|
167
189
|
|
|
@@ -169,7 +191,7 @@ class YandexSmartCaptchaSolver {
|
|
|
169
191
|
* Второй запрос к Yandex SmartCaptcha
|
|
170
192
|
* @private
|
|
171
193
|
*/
|
|
172
|
-
async _secondCheck(captchaKey) {
|
|
194
|
+
async _secondCheck(captchaKey, axiosInstance) {
|
|
173
195
|
this._log('Performing second check request...', 'debug');
|
|
174
196
|
|
|
175
197
|
const url = `https://smartcaptcha.yandexcloud.net/check?host=${this.config.host}&sitekey=${this.config.siteKey}&href=${encodeURIComponent(this.config.siteUrl)}`;
|
|
@@ -183,7 +205,7 @@ class YandexSmartCaptchaSolver {
|
|
|
183
205
|
'Sec-Fetch-Site': 'same-origin'
|
|
184
206
|
};
|
|
185
207
|
|
|
186
|
-
const response = await
|
|
208
|
+
const response = await axiosInstance.post(url, data, { headers });
|
|
187
209
|
return response.data;
|
|
188
210
|
}
|
|
189
211
|
|
|
@@ -191,10 +213,10 @@ class YandexSmartCaptchaSolver {
|
|
|
191
213
|
* Получить изображение капчи
|
|
192
214
|
* @private
|
|
193
215
|
*/
|
|
194
|
-
async _getImage(imageUrl) {
|
|
216
|
+
async _getImage(imageUrl, axiosInstance) {
|
|
195
217
|
this._log('Downloading captcha image...', 'debug');
|
|
196
218
|
|
|
197
|
-
const response = await
|
|
219
|
+
const response = await axiosInstance.get(imageUrl, {
|
|
198
220
|
responseType: 'arraybuffer',
|
|
199
221
|
headers: {
|
|
200
222
|
'Referer': 'https://smartcaptcha.yandexcloud.net/'
|
|
@@ -298,7 +320,7 @@ class YandexSmartCaptchaSolver {
|
|
|
298
320
|
* Отправить результат в Yandex
|
|
299
321
|
* @private
|
|
300
322
|
*/
|
|
301
|
-
async _submit(captchaKey, encodedResult) {
|
|
323
|
+
async _submit(captchaKey, encodedResult, axiosInstance) {
|
|
302
324
|
this._log('Submitting answer to Yandex...', 'info');
|
|
303
325
|
|
|
304
326
|
// Задержка для имитации человека
|
|
@@ -318,37 +340,45 @@ class YandexSmartCaptchaSolver {
|
|
|
318
340
|
'Sec-Fetch-Site': 'same-origin'
|
|
319
341
|
};
|
|
320
342
|
|
|
321
|
-
const response = await
|
|
343
|
+
const response = await axiosInstance.post(url, data, { headers });
|
|
322
344
|
return response.data;
|
|
323
345
|
}
|
|
324
346
|
|
|
325
347
|
/**
|
|
326
348
|
* Решить капчу
|
|
349
|
+
* @param {Object} [proxy] - Настройки SOCKS5 прокси (опционально)
|
|
350
|
+
* @param {string} [proxy.host] - Хост прокси (например: '127.0.0.1')
|
|
351
|
+
* @param {number} [proxy.port] - Порт прокси (например: 1080)
|
|
352
|
+
* @param {string} [proxy.username] - Логин для прокси (опционально)
|
|
353
|
+
* @param {string} [proxy.password] - Пароль для прокси (опционально)
|
|
327
354
|
* @returns {Promise<Object>} Результат с полями status и token (spravka)
|
|
328
355
|
* @throws {Error} При неудаче
|
|
329
356
|
* @example
|
|
330
|
-
* const result = await solver.solve();
|
|
357
|
+
* const result = await solver.solve({ host: '127.0.0.1', port: 1080 });
|
|
331
358
|
* console.log(result); // { status: 'ok', token: 'dD0x...' }
|
|
332
359
|
*/
|
|
333
|
-
async solve() {
|
|
360
|
+
async solve(proxy = null) {
|
|
334
361
|
let imageBuffer = null;
|
|
335
362
|
|
|
336
363
|
try {
|
|
337
364
|
this._log('Starting captcha solving process...', 'info');
|
|
338
365
|
|
|
366
|
+
// Создаем axios инстанс с прокси
|
|
367
|
+
const axiosInstance = this._createAxiosInstance(proxy);
|
|
368
|
+
|
|
339
369
|
// Генерируем GUID
|
|
340
370
|
const guid = uuidv4();
|
|
341
371
|
this._log(`Generated GUID: ${guid}`, 'debug');
|
|
342
372
|
|
|
343
373
|
// Первый запрос
|
|
344
|
-
const firstResponse = await this._firstCheck();
|
|
374
|
+
const firstResponse = await this._firstCheck(axiosInstance);
|
|
345
375
|
if (!firstResponse.captcha?.key) {
|
|
346
376
|
throw new Error('No captcha key received from first request');
|
|
347
377
|
}
|
|
348
378
|
this._log('First captcha key received', 'debug');
|
|
349
379
|
|
|
350
380
|
// Второй запрос
|
|
351
|
-
const secondResponse = await this._secondCheck(firstResponse.captcha.key);
|
|
381
|
+
const secondResponse = await this._secondCheck(firstResponse.captcha.key, axiosInstance);
|
|
352
382
|
if (!secondResponse.captcha?.image) {
|
|
353
383
|
throw new Error('No captcha image URL received');
|
|
354
384
|
}
|
|
@@ -357,23 +387,22 @@ class YandexSmartCaptchaSolver {
|
|
|
357
387
|
this._log('Second captcha key received', 'debug');
|
|
358
388
|
|
|
359
389
|
// Получаем и распознаем изображение
|
|
360
|
-
imageBuffer = await this._getImage(secondResponse.captcha.image);
|
|
390
|
+
imageBuffer = await this._getImage(secondResponse.captcha.image, axiosInstance);
|
|
361
391
|
const recognizedText = await this._recognize(imageBuffer);
|
|
362
392
|
|
|
363
393
|
// Кодируем и отправляем
|
|
364
394
|
const encodedResult = this._encode(recognizedText);
|
|
365
395
|
this._log(`Encoded result: ${encodedResult}`, 'debug');
|
|
366
396
|
|
|
367
|
-
const finalResponse = await this._submit(captchaKey, encodedResult);
|
|
397
|
+
const finalResponse = await this._submit(captchaKey, encodedResult, axiosInstance);
|
|
368
398
|
|
|
369
399
|
// Проверяем результат
|
|
370
400
|
if (finalResponse.status === 'ok') {
|
|
371
401
|
this._log('Captcha solved successfully!', 'info');
|
|
372
402
|
this._saveImage(imageBuffer, recognizedText, true);
|
|
373
|
-
|
|
374
403
|
return {
|
|
375
404
|
status: 'ok',
|
|
376
|
-
token: finalResponse.
|
|
405
|
+
token: finalResponse.spravka
|
|
377
406
|
};
|
|
378
407
|
} else {
|
|
379
408
|
// Неудача - сообщаем XEvil
|
|
@@ -398,18 +427,19 @@ class YandexSmartCaptchaSolver {
|
|
|
398
427
|
* Решить капчу с автоматическими повторными попытками
|
|
399
428
|
* @param {number} [maxAttempts=3] - Максимальное количество попыток
|
|
400
429
|
* @param {number} [retryDelay=3000] - Задержка между попытками (мс)
|
|
430
|
+
* @param {Object} [proxy] - Настройки SOCKS5 прокси (опционально)
|
|
401
431
|
* @returns {Promise<Object>} Результат с полями status и token
|
|
402
432
|
* @throws {Error} Если все попытки неудачны
|
|
403
433
|
* @example
|
|
404
|
-
* const result = await solver.solveWithRetry(5, 4000);
|
|
434
|
+
* const result = await solver.solveWithRetry(5, 4000, { host: '127.0.0.1', port: 1080 });
|
|
405
435
|
*/
|
|
406
|
-
async solveWithRetry(maxAttempts = 3, retryDelay = 3000) {
|
|
436
|
+
async solveWithRetry(maxAttempts = 3, retryDelay = 3000, proxy = null) {
|
|
407
437
|
this._log(`Will attempt to solve up to ${maxAttempts} times`, 'info');
|
|
408
438
|
|
|
409
439
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
410
440
|
try {
|
|
411
441
|
this._log(`Attempt ${attempt}/${maxAttempts}`, 'info');
|
|
412
|
-
const result = await this.solve();
|
|
442
|
+
const result = await this.solve(proxy);
|
|
413
443
|
this._log(`Successfully solved on attempt ${attempt}!`, 'info');
|
|
414
444
|
return result;
|
|
415
445
|
} catch (error) {
|
|
@@ -426,4 +456,4 @@ class YandexSmartCaptchaSolver {
|
|
|
426
456
|
}
|
|
427
457
|
}
|
|
428
458
|
|
|
429
|
-
module.exports = YandexSmartCaptchaSolver;
|
|
459
|
+
module.exports = YandexSmartCaptchaSolver;
|