Как обойти капчу на платформе для парсинга сайтов Diggernaut: Решаем Google reCaptcha v2

Гугл рекапча (reCaptcha v2) перестала быть проблемой для наших пользователей. Мы внедрили интеграцию с популярным сервисов по обходу капчи Death By Captcha и теперь ваши скраперы могут легко обходить самые современные капчи.

Давайте посмотрим, как выглядит reCaptcha v2:

Если вы видите именно такую капчу на сайте. который вам нужно отпарсить, то эта статья вам обязательно поможет. Мы постараемя дать вам исчерпывающее руководство на реальном примере, так, чтобы вы смогли легко внедрить подобное решение для вашего сайта. Мы же будем парсить следующий сайт: http://www.receita.fazenda.gov.br/PessoaJuridica/CNPJ/cnpjreva/Cnpjreva_Solicitacao2.asp.

Для того, чтобы пользовать этим функционалом вам нужно иметь собственный аккаунт в службе Death by Captcha. Их услуги не бесплатны, стоимость решения 100 капч составляет примерно 2.89$ (цена актуальна на 28.02.2018).

Решение капчи происходит автоматически, вам нужно лишь загрузить страницу с капчей в ваш скрапер и вызвать специальную команду captcha_resolve с определенными параметрами:

prodiver: провайдер решений для капчи, нужно установить значение deathbycaptcha.com
type: тип капчи, нужно установить значение nocaptchav2
username: имя пользователя вашего аккаунта в системе death by captcha
password: пароль вашего аккаунта в системе death by captcha

ВНИМАНИЕ!!! Для того чтобы капча этого типа была успешно решена, люди, которые будут вручную решать вашу капчу должны будут это делать под тем же IP адресом, что использует ваш парсер. Поэтому, единственный вариант этого достичь — использовать ВАШ СОБСТВЕННЫЙ ПРОКСИ СЕРВЕР в конфигурации вашего диггера. Наши штатные прокси сервера не могут быть доступны с IP адресов, вне нашей основной сети, поэтому штатные прокси просто не будут работать в этом случае. В дальнейшем мы внедрим специальный пул прокси серверов для этой задачи, но пока вы должны будете использовать свой прокси.

Базовый код нашего парсера будет таким:

---
config:
    debug: 2
    agent: Firefox
    proxy: ВАШ ПРОКСИ НУЖНО ВСТАВИТЬ СЮДА
do:
# Мы будем повторять неудавшийся запрос, поэтому пропишем значение переменной,
# которую будет использовать опция repeat
- variable_set:
    field: repeat
    value: "yes"
# Загружаем страницу с капчей
- walk:
    to: http://www.receita.fazenda.gov.br/PessoaJuridica/CNPJ/cnpjreva/cnpjreva_solicitacao2.asp
    repeat: 
    do:
        # Решаем капчу
    - captcha_resolve:
        provider: deathbycaptcha.com
        type: nocaptchav2
        username: ВАШЕ ИМЯ ПОЛЬЗОВАТЕЛЯ В СЛУЖБЕ DBC
        password: ВАШ ПАРОЛЬ В СЛУЖБЕ DBC

Пока не запускайте ваш парсер, просто изучите код. Если капча решена успешно, токен будет сохранен в переменной captcha. Поэтому, первым делом после решения капчи мы должны проверить наличие токена в переменной. Если токен есть, мы отключим опцию repeat и передадим токен на сервер вместе с другими параметрами нашего запроса. Если токена нет, запрос будет повторен, поскольку опция repeat установлена в «yes».

---
config:
    debug: 2
    agent: Firefox
    proxy: ВАШ ПРОКСИ НУЖНО ВСТАВИТЬ СЮДА
do:
# Мы будем повторять неудавшийся запрос, поэтому пропишем значение переменной,
# которую будет использовать опция repeat
- variable_set:
    field: repeat
    value: "yes"
# Загружаем страницу с капчей
- walk:
    to: http://www.receita.fazenda.gov.br/PessoaJuridica/CNPJ/cnpjreva/cnpjreva_solicitacao2.asp
    repeat: 
    do:
    # Решаем капчу
    - captcha_resolve:
        provider: deathbycaptcha.com
        type: nocaptchav2
        username: ВАШЕ ИМЯ ПОЛЬЗОВАТЕЛЯ В СЛУЖБЕ DBC
        password: ВАШ ПАРОЛЬ В СЛУЖБЕ DBC
    # Переходим в блок body
    - find:
        path: body
        do:
        # Читаем значение переменной captcha в регистр
        - variable_get: captcha
        # Проверяем, не пустой ли у нас регистр
        - if:
            match: \w+
            do:
            # Если не пустой, отключаем repeat
            - variable_set:
                field: repeat
                value: "no"
            # Передаем токен и другие параметры на сайт с которого мы собираем информацию.
            # В данном случае мы пытаемся получить данные о компании по его ИНН (CNPJ)
            - walk:
                to:
                    post: http://www.receita.fazenda.gov.br/PessoaJuridica/CNPJ/cnpjreva/valida_recaptcha.asp
                    data:
                        origem: comprovante
                        cnpj: 05754558000186
                        g-recaptcha-response: 
                        submit1: Consultar
                        search_type: cnpj
                do:
                - find:
                    path: 'div#principal'
                    do:
                    - object_new: item
                    - find:
                        path: td:haschild(font:contains('NÚMERO DE INSCRIÇÃO')) b
                        slice: 0
                        do:
                        - parse
                        - space_dedupe
                        - trim
                        - object_field_set:
                            object: item
                            field: registration_number
                    - find:
                        path: td:haschild(font:contains('DATA DE ABERTURA')) b
                        slice: 0
                        do:
                        - parse
                        - space_dedupe
                        - trim
                        - object_field_set:
                            object: item
                            field: registration_date
                    - find:
                        path: td:haschild(font:contains('NOME EMPRESARIAL')) b
                        slice: 0
                        do:
                        - parse
                        - space_dedupe
                        - trim
                        - object_field_set:
                            object: item
                            field: company_name
                    - find:
                        path: td:haschild(font:contains('CÓDIGO E DESCRIÇÃO DA ATIVIDADE ECONÔMICA PRINCIPAL')) b
                        slice: 0
                        do:
                        - parse
                        - space_dedupe
                        - trim
                        - object_field_set:
                            object: item
                            field: primary_code
                    - find:
                        path: td:haschild(font:contains('CÓDIGO E DESCRIÇÃO DAS ATIVIDADES ECONÔMICAS SECUNDÁRIAS')) b
                        do:
                        - parse
                        - space_dedupe
                        - trim
                        - object_field_push:
                            object: item
                            field: secondary_codes
                    - find:
                        path: td:haschild(font:contains('CÓDIGO E DESCRIÇÃO DA NATUREZA JURÍDICA')) b
                        slice: 0
                        do:
                        - parse
                        - space_dedupe
                        - trim
                        - object_field_set:
                            object: item
                            field: legal_code
                    - find:
                        path: td:haschild(font:contains('LOGRADOURO')) b
                        slice: 0
                        do:
                        - parse
                        - space_dedupe
                        - trim
                        - object_field_set:
                            object: item
                            field: street
                    - find:
                        path: td:haschild(font:contains('BAIRRO/DISTRITO')) b
                        slice: 0
                        do:
                        - parse
                        - space_dedupe
                        - trim
                        - object_field_set:
                            object: item
                            field: district
                    - find:
                        path: td:haschild(font:contains('MUNICÍPIO')) b
                        slice: 0
                        do:
                        - parse
                        - space_dedupe
                        - trim
                        - object_field_set:
                            object: item
                            field: municipal
                    - find:
                        path: td:haschild(font:contains('TELEFONE')) b
                        slice: 0
                        do:
                        - parse
                        - space_dedupe
                        - trim
                        - object_field_set:
                            object: item
                            field: phone
                    - find:
                        path: td:haschild(font:contains('E-MAIL')) b
                        slice: 0
                        do:
                        - parse
                        - space_dedupe
                        - trim
                        - object_field_set:
                            object: item
                            field: email
                    - object_save:
                        name: item

Если вы запустите этот парсер вы получите следующий датасет

[{
    "item": {
        "company_name": "LIST - LOGISTICA INTEGRADA, SERVICOS E TRANSPORTES LTDA",
        "district": "COROADO",
        "legal_code": "206-2 - Sociedade Empresária Limitada",
        "municipal": "MANAUS",
        "phone": "(92) 3622-7885",
        "primary_code": "52.12-5-00 - Carga e descarga",
        "registration_date": "26/06/2003",
        "registration_number": "05.754.558/0001-86",
        "secondary_codes": [
            "49.30-2-02 - Transporte rodoviário de carga, exceto produtos perigosos e mudanças, intermunicipal, interestadual e internacional",
            "77.39-0-99 - Aluguel de outras máquinas e equipamentos comerciais e industriais não especificados anteriormente, sem operador",
            "77.19-5-99 - Locação de outros meios de transporte não especificados anteriormente, sem condutor",
            "52.29-0-99 - Outras atividades auxiliares dos transportes terrestres não especificadas anteriormente",
            "49.30-2-01 - Transporte rodoviário de carga, exceto produtos perigosos e mudanças, municipal",
            "52.50-8-03 - Agenciamento de cargas, exceto para o transporte marítimo"
        ],
        "street": "R PROFESSORA RAYMUNDA MAGALHAES"
    }
}]

Подобные решения часто используются в сценариях типа «Данные по требованию». Когда пользователь на вашем сайте вводит номер, ваш сайт принимает ввод от пользователя и делает запрос на API платформы Diggernaut. Этот запрос запускает диггер с переданным параметром и возвращает собранные данные обратно на ваш сервер в режиме реального времени. А ваш сервер показывает их вашему пользователю. Однако примите во внимание, что процесс решения капчи может занимать продолжительное время, например решение reCaptcha v2 может занимать более 1 минуты. Это нужно учитывать при проектировании вашего приложения.

В любом случае, мы надеемся, что статья была вам полезна и поможет вам внедрить это решение для вашего парсера. Мы планируем добавлять решения для других видов капчи, следите за обновлениями.

Михаил Сисин: Со-основатель облачного сервиса по сбору информации и парсингу сайтов Diggernaut. Работает в области сбора и анализа данных, а также разработки систем искусственного интеллекта и машинного обучения  более десяти лет.
Related Post

This website uses cookies.