Intégrations

Crawlee + CaptchaAI : intégration du framework de scraping moderne

Crawlee est un framework de scraping Node.js moderne d'Apify. Voici comment intégrer CaptchaAI pour la résolution automatique de CAPTCHA dans vos robots Crawlee.


Pourquoi Crawlee + CaptchaAI

Caractéristique Avantage
Gestion de session intégrée Empreintes digitales cohérentes avec CAPTCHA résolus
Nouvelle tentative automatique Réessayez les demandes ayant échoué après la résolution du CAPTCHA
Rotation des procurations Associer avec la prise en charge du proxy CaptchaAI
File d'attente des demandes La file d'attente CAPTCHA est résolue parallèlement au scraping

Intégration de base

const { CheerioCrawler } = require('crawlee');
const https = require('https');

const API_KEY = process.env.CAPTCHAAI_API_KEY;

async function solveCaptcha(sitekey, pageurl) {
    // Submit task
    const submitData = new URLSearchParams({
        key: API_KEY,
        method: 'userrecaptcha',
        googlekey: sitekey,
        pageurl: pageurl,
        json: '1',
    });

    const submitResp = await fetch('https://ocr.captchaai.com/in.php', {
        method: 'POST',
        body: submitData,
    });
    const submitResult = await submitResp.json();

    if (submitResult.status !== 1) {
        throw new Error(`Submit error: ${submitResult.request}`);
    }

    const taskId = submitResult.request;

    // Poll for result
    await new Promise(r => setTimeout(r, 15000));

    for (let i = 0; i < 24; i++) {
        const pollResp = await fetch(
            `https://ocr.captchaai.com/res.php?key=${API_KEY}&action=get&id=${taskId}&json=1`
        );
        const pollResult = await pollResp.json();

        if (pollResult.status === 1) return pollResult.request;
        if (pollResult.request !== 'CAPCHA_NOT_READY') {
            throw new Error(`Solve error: ${pollResult.request}`);
        }

        await new Promise(r => setTimeout(r, 5000));
    }

    throw new Error('Solve timeout');
}

// Crawlee spider with CAPTCHA handling
const crawler = new CheerioCrawler({
    maxConcurrency: 5,
    requestHandlerTimeoutSecs: 180,

    async requestHandler({ request, $, log }) {
        // Check if page has CAPTCHA
        const captchaDiv = $('[data-sitekey]');

        if (captchaDiv.length > 0) {
            const sitekey = captchaDiv.attr('data-sitekey');
            log.info(`CAPTCHA found on ${request.url}, solving...`);

            const token = await solveCaptcha(sitekey, request.url);
            log.info('CAPTCHA solved, submitting form');

            // Submit form with token
            const formData = new URLSearchParams({
                'g-recaptcha-response': token,
            });

            const resp = await fetch(request.url, {
                method: 'POST',
                body: formData,
            });
            const html = await resp.text();
            // Parse the result page...
        }

        // Extract data
        const title = $('title').text();
        const data = $('table tr').map((i, row) => ({
            col1: $(row).find('td:eq(0)').text().trim(),
            col2: $(row).find('td:eq(1)').text().trim(),
        })).get();

        log.info(`Scraped ${data.length} rows from ${request.url}`);
    },

    failedRequestHandler({ request, log }) {
        log.error(`Failed: ${request.url}`);
    },
});

// Run
(async () => {
    await crawler.run([
        'https://example.com/page1',
        'https://example.com/page2',
    ]);
})();

DramaturgeCrawler avec CAPTCHA

const { PlaywrightCrawler } = require('crawlee');

const crawler = new PlaywrightCrawler({
    maxConcurrency: 3,
    requestHandlerTimeoutSecs: 180,
    launchContext: {
        launchOptions: {
            headless: true,
            args: ['--disable-blink-features=AutomationControlled'],
        },
    },

    async requestHandler({ request, page, log }) {
        await page.goto(request.url, { waitUntil: 'networkidle' });

        // Check for reCAPTCHA
        const sitekey = await page.evaluate(() => {
            const el = document.querySelector('[data-sitekey]');
            return el ? el.getAttribute('data-sitekey') : null;
        });

        if (sitekey) {
            log.info(`CAPTCHA detected, solving for ${request.url}`);

            const token = await solveCaptcha(sitekey, request.url);

            // Inject token
            await page.evaluate((t) => {
                const ta = document.querySelector('[name="g-recaptcha-response"]');
                if (ta) {
                    ta.style.display = 'block';
                    ta.value = t;
                }
                // Trigger callback
                const widget = document.querySelector('.g-recaptcha');
                if (widget) {
                    const cb = widget.getAttribute('data-callback');
                    if (cb && typeof window[cb] === 'function') {
                        window[cb](t);
                    }
                }
            }, token);

            await page.click('button[type="submit"]');
            await page.waitForNavigation({ waitUntil: 'networkidle' });
        }

        // Extract data
        const title = await page.title();
        const content = await page.textContent('body');
        log.info(`Page: ${title}, length: ${content.length}`);
    },
});

Résolution de CAPTCHA en fonction de la session

const { CheerioCrawler, Session } = require('crawlee');

const crawler = new CheerioCrawler({
    useSessionPool: true,
    sessionPoolOptions: {
        maxPoolSize: 10,
        sessionOptions: {
            maxUsageCount: 50,
        },
    },

    async requestHandler({ request, $, session, log }) {
        // If blocked, solve CAPTCHA and mark session as usable
        if ($('.captcha-container').length > 0) {
            const sitekey = $('[data-sitekey]').attr('data-sitekey');
            const token = await solveCaptcha(sitekey, request.url);

            // Store token in session for subsequent requests
            session.userData = session.userData || {};
            session.userData.captchaToken = token;
            session.userData.tokenTime = Date.now();

            log.info('CAPTCHA solved, session updated');
        }

        // Normal scraping
        const items = $('div.item').map((i, el) => ({
            name: $(el).find('.name').text().trim(),
            price: $(el).find('.price').text().trim(),
        })).get();

        log.info(`Found ${items.length} items`);
    },
});

FAQ

Crawlee dispose-t-il d'un support CAPTCHA intégré ?

Non. Crawlee gère les sessions, les proxys et les tentatives, mais vous devez ajouter la résolution CAPTCHA via CaptchaAI ou un autre service.

Quel robot Crawlee dois-je utiliser ?

Utilisez CheerioCrawler pour les pages statiques, PlaywrightCrawler pour les pages rendues en JavaScript avec CAPTCHA et PuppeteerCrawler comme alternative à Playwright.

Puis-je utiliser Crawlee avec CaptchaAI sur Apify ?

Oui. Déployez votre acteur Crawlee sur Apify et utilisez CaptchaAI via des appels API HTTP. Définissez la clé API en tant que variable d'environnement Apify.


Guides connexes


Ajouter la résolution CAPTCHA à Crawlee -récupérez votre clé CaptchaAI.

Les commentaires sont désactivés pour cet article.