Node.js excelle dans les charges de travail de scraping I/O-heavy. Lorsque les sites cibles diffusent des CAPTCHA, l'API de CaptchaAI les résout tandis que votre script gère les requêtes HTTP. Ce didacticiel couvre le flux de travail complet utilisant axios et cheerio.
Exigences
| Exigence | Détails |
|---|---|
| Node.js 16+ | Avec npm |
| axios | npm install axios |
| bravo | npm install cheerio |
| Clé API CaptchaAI | Depuiscaptchaai.com |
Le module solveur CaptchaAI
// captcha-solver.js
const axios = require("axios");
class CaptchaSolver {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = "https://ocr.captchaai.com";
}
async _submit(params) {
params.key = this.apiKey;
const resp = await axios.get(`${this.baseUrl}/in.php`, { params });
if (!resp.data.startsWith("OK|")) {
throw new Error(`Submit error: ${resp.data}`);
}
return resp.data.split("|")[1];
}
async _poll(taskId, timeout = 300000) {
const deadline = Date.now() + timeout;
while (Date.now() < deadline) {
await new Promise((r) => setTimeout(r, 5000));
const resp = await axios.get(`${this.baseUrl}/res.php`, {
params: { key: this.apiKey, action: "get", id: taskId },
});
if (resp.data === "CAPCHA_NOT_READY") continue;
if (resp.data.startsWith("OK|")) return resp.data.split("|")[1];
throw new Error(`Solve error: ${resp.data}`);
}
throw new Error("Solve timed out");
}
async solveRecaptchaV2(siteKey, pageUrl) {
const taskId = await this._submit({
method: "userrecaptcha",
googlekey: siteKey,
pageurl: pageUrl,
});
return this._poll(taskId);
}
async solveRecaptchaV3(siteKey, pageUrl, action = "verify") {
const taskId = await this._submit({
method: "userrecaptcha",
googlekey: siteKey,
pageurl: pageUrl,
version: "v3",
action,
});
return this._poll(taskId);
}
async solveTurnstile(siteKey, pageUrl) {
const taskId = await this._submit({
method: "turnstile",
sitekey: siteKey,
pageurl: pageUrl,
});
return this._poll(taskId);
}
}
module.exports = CaptchaSolver;
Supprimer une page protégée par reCAPTCHA
const axios = require("axios");
const cheerio = require("cheerio");
const CaptchaSolver = require("./captcha-solver");
const solver = new CaptchaSolver("YOUR_API_KEY");
async function scrapeProtectedPage(url) {
// Step 1: Load the page
const { data: html } = await axios.get(url, {
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
},
});
const $ = cheerio.load(html);
// Step 2: Extract site key
const siteKey = $(".g-recaptcha").attr("data-sitekey");
if (!siteKey) {
console.log("No CAPTCHA found, page loaded directly");
return html;
}
console.log("Site key found:", siteKey);
// Step 3: Solve the CAPTCHA
const token = await solver.solveRecaptchaV2(siteKey, url);
console.log("Token received:", token.substring(0, 50));
// Step 4: Submit with the token
const result = await axios.post(
url,
new URLSearchParams({
"g-recaptcha-response": token,
q: "search query",
}),
{
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
},
}
);
return result.data;
}
Gratter plusieurs pages simultanément
async function scrapePages(urls, siteKey, concurrency = 3) {
const results = [];
const queue = [...urls];
const worker = async () => {
while (queue.length > 0) {
const url = queue.shift();
try {
const token = await solver.solveRecaptchaV2(siteKey, url);
const { data } = await axios.post(
url,
new URLSearchParams({ "g-recaptcha-response": token }),
{
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
},
}
);
results.push({ url, data, success: true });
console.log(`Scraped: ${url}`);
} catch (err) {
results.push({ url, error: err.message, success: false });
console.error(`Failed: ${url} - ${err.message}`);
}
}
};
// Run workers concurrently
const workers = Array(concurrency)
.fill(null)
.map(() => worker());
await Promise.all(workers);
return results;
}
// Usage
const urls = [
"https://example.com/page/1",
"https://example.com/page/2",
"https://example.com/page/3",
];
const results = await scrapePages(urls, "6Le-wvkS...", 3);
Gestion des cookies et des sessions
Utilisez axios avec persistance des cookies pour les sites qui nécessitent des cookies de session :
const { wrapper } = require("axios-cookiejar-support");
const { CookieJar } = require("tough-cookie");
const jar = new CookieJar();
const client = wrapper(
axios.create({
jar,
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
},
})
);
async function scrapeWithSession(url, siteKey) {
// Initial page load sets cookies
await client.get(url);
// Solve CAPTCHA
const token = await solver.solveRecaptchaV2(siteKey, url);
// Submit with maintained cookies
const result = await client.post(
url,
new URLSearchParams({ "g-recaptcha-response": token })
);
return result.data;
}
Analyser les résultats avec Cheerio
function parseResults(html) {
const $ = cheerio.load(html);
const items = [];
$(".result-item").each((_, el) => {
items.push({
title: $(el).find(".title").text().trim(),
url: $(el).find("a").attr("href"),
description: $(el).find(".description").text().trim(),
});
});
return items;
}
Dépannage
| Problème | Parce que | Corriger |
|---|---|---|
CAPTCHA_NOT_READY boucle indéfiniment |
Mauvaise clé de site ou résolution lente | Vérifiez la clé du site ; augmenter le délai d'attente |
403 Forbidden sur POST |
Cookies ou en-têtes manquants | Utiliser des cookies de session ; ajouter l'en-tête Referer |
| Cheerio ne trouve pas d'éléments | Contenu dynamique | Utiliser Puppeteer pour les sites rendus en JS |
ECONNREFUSED |
Tarif limité par site cible | Ajouter des retards ; faire pivoter les proxys |
FAQ
Quand dois-je utiliser Puppeteer au lieu d’axios ?
Utilisez axios + cheerio lorsque le site cible renvoie du HTML avec des soumissions de formulaire standard. Utilisez Puppeteer lorsque le site nécessite l'exécution de JavaScript, un rendu dynamique ou des interactions utilisateur complexes.
Puis-je résoudre plusieurs CAPTCHA en même temps ?
Oui. Soumettez simultanément plusieurs tâches CAPTCHA à CaptchaAI et interrogez chaque résultat. L’exemple de scraping simultané ci-dessus illustre ce modèle.
Comment gérer les sites protégés par Cloudflare ?
Si le site utilise Turnstile, utilisez solver.solveTurnstile(). Pour les pages complètes du défi Cloudflare, utilisezRésolution de Cloudflare Challengequi renvoie les cookies cf_clearance.
Guides connexes
- Résolution de CAPTCHA par le marionnettiste avec Node.js
- Grattage de CAPTCHA avec Python
- Rotation du proxy pour le grattage de CAPTCHA