JavaScript парсеры: расширенный функционал A-Parser

решил проблему, нектуально...
 
Последнее редактирование:
С версии 1.1.772 добавлено автоматическое версионирование при сохранении кода парсера через встроенный редактор:
Код:
        this.defaultConf = {
            version: '0.1.1',
  • Версия имеет формат: Major.Minor.Revision
  • Значение Revision(последняя цифра) автоматически увеличивается при каждом сохранении
  • Остальные значения(Major, Minor) можно менять вручную, а также сбрасывать Revision в 0 для
  • Если по каким то причинам необходимо менять Revision только вручную, то версию необходимо заключить в двойные кавычки ""
 
С версии 1.1.774 добавлен функционал по работе с каптчей:
  • yield this.captcha.recognize(preset, image, type, overrides) - загрузка каптчи для распознавания, image - бинарные данные картинки для распознавания, preset указывает на пресет для Util::AntiGate, type указывается один из: 'jpeg', 'gif', 'png', результатом будет хэш с полями answer(если задан - это текст картинки), id(id каптчи, для возможности в дальнейшем сообщить об ошибке через reportBad), error(текстовая ошибка, если answer не задан)
  • yield this.captcha.recognizeFromUrl(preset, url, overrides) - аналогично предыдущему методу, но загрузка каптчи будет выполнятся автоматически по ссылке, без использования прокси
  • yield this.captcha.reportBad(preset, id, overrides) - сообщить сервису что каптча разгадана неверно
Небольшой пример по использованию:
Код:
    *parse(set, results) {
        set.query = 'https://a-parser.com/img/captcha.jpeg'
      
        //Manual download captcha + recognize + report bad
        let response = yield this.request('GET', set.query, {}, {});

        if(response.success) {
            const captcha = yield this.captcha.recognize('antigate.com', response.data, 'jpeg');
            if(captcha.answer) {
                this.logger.put('Captcha Answer: ' + captcha.answer);
                if(captcha.answer != 'ifignt eyelids') {
                    yield this.captcha.reportBad('antigate.com', captcha.id);
                }
            }
            else {
                this.logger.put('Captcha recognize error: ' + captcha.error);
            }
            this.logger.put('Recognize from data: ' + JSON.stringify(captcha));
        }
      
        //Auto download captcha
        const captcha = yield this.captcha.recognizeFromUrl('antigate.com', set.query);
      
        this.logger.put('Recognize from url: ' + JSON.stringify(captcha));
      
        results.success = 1;

        return results;
    }
 
  • Обновлен пример парсинга Mail.Ru с возможностью использовать антигейт через yield this.captcha.*
 
Последнее редактирование:
Очень хотелось бы увидеть полный аналог парсера Net::HTTP на JavaScript с поддержкой антигейта.
 
  • Like
Реакции: btr
Если можно то на примере поисковика Rambler.
 
this.request это и есть аналог этого парсера, поддержка каптчи уже реализована же :)
 
Добрый день. Можно ли 5 пример "Парсинг текстовки по ключу" HTML::TextExtractor заменить на NET::HTTP? Попытался по аналоги переписать, но не вышло:
class Parser {
constructor() {
this.defaultConf = {
results: {
flat: [
['key', 'Keyword'],
['link', 'Link'],
['data', 'Data'],
]
},
results_format: "$key - $link\\n$data\\n\\n",
search_engine: 'SE::Google',
SE_Google_preset: 'default',
SE_Yandex_preset: 'default',
NET_HTTP_preset: 'default',
};
this.editableConf = [
['SE_Google_preset', ['combobox', 'SE::Google preset']],
['SE_Yandex_preset', ['combobox', 'SE::Yandex preset']],
['NET_HTTP_preset', ['combobox', 'NET::HTTP preset']],
['search_engine', ['combobox', 'Search engine', ['SE::Google', 'Google'], ['SE::Yandex', 'Yandex']]],
];
}

*parse(set, results) {
return yield* set.lvl == 0 ? this.parseSE(set, results) : this.parseText(set, results);
}

*parseSE(set, results) {
this.logger.put("Start scraping query: " + set.query);

this.logger.put(`Use ${this.conf.search_engine}`);
let SEresp = yield this.parser.request(
this.conf.search_engine,
this.conf[this.conf.search_engine.replace(/::/, '_') + '_preset'],
set.query
);

if(SEresp.info.success) {
let link_count = 0;
let step = this.conf.search_engine == 'SE::Google' ? 3 : 5;
for (let i = 0; i < SEresp.serp.length; i += step) {
const link = SEresp.serp;
this.query.add(link);
link_count += 1;
}
this.logger.put("Added " + link_count + " links");
results.success = 1;
results.SKIP = 1;
return results;
}
else {
this.logger.put(`Error scraping ${this.conf.search_engine}`);
results.success = 0;
return results;
}
}

*parseText(set, results) {
this.logger.put("Scraping text from " + set.query);
let response = yield this.parser.request('NET::HTTP', this.conf.NET_HTTP_preset, set.query);
results.key = set.first;
results.link = set.query;
if(response.info.success) {
results.data = response.data;//????????
this.logger.put(set.query + " - " + response.data.length + " blocks, " + results.data.length + " chars");
results.success = 1;
}
else {
this.logger.put(set.query + " - error scraping text");
results.success = 0;
}
return results;
}
}
 
Добрый день.
Легко. Достаточно заменить HTML::TextExtractor на Net::HTTP и выводить не объединенные блоки текста, а просто data.
Код:
class Parser {
    constructor() {
        this.defaultConf = {
            version: '0.1.1',
            results: {
                flat: [
                    ['key', 'Keyword'],
                    ['link', 'Link'],
                    ['content', 'Page content'],
                ]
            },
            results_format: "$key - $link\\n$content\n\\n",
            search_engine: 'SE::Google',
            SE_Google_preset: 'default',
            SE_Yandex_preset: 'default',
            Net_HTTP_preset: 'default',
        };
        this.editableConf = [
            ['SE_Google_preset', ['combobox', 'SE::Google preset']],
            ['SE_Yandex_preset', ['combobox', 'SE::Yandex preset']],
            ['Net_HTTP_preset_preset', ['combobox', 'Net::HTTP preset']],
            ['search_engine', ['combobox', 'Search engine', ['SE::Google', 'Google'], ['SE::Yandex', 'Yandex']]],
        ];
    }

       
    *parse(set, results) {
        return yield* set.lvl == 0 ? this.parseSE(set, results) : this.parseContent(set, results);
    }
   
    *parseSE(set, results) {
        this.logger.put("Start scraping query: " + set.query);

        this.logger.put(`Use ${this.conf.search_engine}`);
        let SEresp = yield this.parser.request(
            this.conf.search_engine,
            this.conf[this.conf.search_engine.replace(/::/, '_') + '_preset'],
            set.query
        );

        if(SEresp.info.success) {
            let link_count = 0;
            let step = this.conf.search_engine == 'SE::Google' ? 3 : 5;
            for (let i = 0; i < SEresp.serp.length; i += step) {
                const link = SEresp.serp[i];
                this.query.add(link);
                link_count += 1;
            }
            this.logger.put("Added " + link_count + " links");
            results.success = 1;
            results.SKIP = 1;
            return results;
        }
        else {
            this.logger.put(`Error scraping ${this.conf.search_engine}`);
            results.success = 0;
            return results;
        }
    }

    *parseContent(set, results) {
        this.logger.put("Scraping content from " + set.query);
        let response = yield this.parser.request('Net::HTTP', this.conf.Net_HTTP_preset, set.query);
        results.key = set.first;
        results.link = set.query;
        if(response.info.success) {
            results.content = response.data;
            results.success = 1;
        }
        else {
            this.logger.put(set.query + " - error scraping content");
            results.success = 0;
        }
        return results;
    }
}
 
С версии 1.1.805 добавлен метод this.util.updateResultsData(results, data) для автоматического заполнения ($pages.$i.data и $data), необходимо вызывать для добавления контента результирующей страницы
 
Последнее редактирование:
С версии 1.1.807 добавлен метод this.util.urlFromHTML(url, [base]), обрабатывает ссылку полученную из HTML кода - декодирует entities(&amp; и т.п.), опционально можно перед base - базовый урл(например урл исходной страницы), таким образом может быть получена полная ссылка
 
С версии 1.1.769 для this.request добавлен параметр attempt, который указывает на текущую попытку, при этом встроенный обработчик попыток игнорируется, пример:
Код:
yield this.request('GET', 'http://domain.com/', {}, {attempt: 3}); // в логе отобразится что текущий запрос - 3яя попытка
ДД. Подскажите, где прочитать как работает встроенный обработчик попыток? Что такое успешная и не успешная попытка?
 
Приветствую
Если я правильно понимаю, то успешная попытка, это попытка когда все запросы вернули положительное значение. т.е. берем 10 листов гугла, если парсер проходит по ним всем и получает данные, то это считается положительной попыткой. Если же парсер прошел ни одной либо прошел < 10, в данном случае, то это неуспешная попытка, хотя результат выведется.
Хотя могу и ошибаться.
 
Немного уточню.
В настройках парсера стоит Кол-во попыток: 1000.

Вариант 1.
Если я выполняю этот запрос, то он будет выполняться пока не получу код ответа 200 и не пройдет валидация контента согласно регулярке в check_content и так до 1000 раз?
При не успешной попытке прокси-сервер меняется?

Код:
let response = yield this.request('GET', 'https://foobar/', {}, {
    check_content: ['<\/html>'],
    decode: 'auto-html',
    parsecodes: {200: 1},
    browser: 1,
});

Вариант 2.
Я вручную управляю счетчиком попыток скачки с помощью параметра attempt.
В этом случае успешность запроса определяется так же, как в 1-м варианте?
Прокси-сервер я здесь меняю сам.

Код:
for(attempt = 1; attempt <= this.conf.proxyretries; attempt++) {
    let response = yield this.request('GET', 'https://foobar/', {}, {
        check_content: ['<\/html>'],
        decode: 'auto-html',
        parsecodes: {200: 1},
        browser: 1,
        attempt: attempt,
    });
    if (response.success) {
        break;
    }
    this.proxy.next();
}
 
Здравствуйте.
1) В первом варианте будет перебирать прокси, пока код ответа не будет 200 и и код страницы не будет соответствовать регулярке в check_content ,либо пока не закончится число попыток. Прокси будут меняться при этоем, если конечно парсите с прокси.
2) В описанном вами 2 варианте успешность запроса определяется так же как и в 1-ом варианте.
 
Скажите, javaScript парсер обрабатывает js скриаты на странице доноре?
У меня такая задача, весть контент на странице выводится через js скрипт, как спарсить с такой страницы?
 
Здравствуйте.
Если контент страницы собирается динамически js скриптом, то нужно использовать инструменты разработчика в браузере и смотреть какие запросы и с какими данными отправляются.
Например на сайте olx.ua чтобы увидеть телефон продавца надо нажать на кнопку и тогда открывается телефон. Открываем инструменты разработчика, смотрим какой запрос добавился при нажатии смотрим его ответ , и если это то что нужно, то отправляем запрос с такими заголовками и переменными.
ev6Ec
 
Вся страница выводится неск скриптами
Если смотреть через браузер, то видна норм страница, если через гет пост, то видны только скрипты.
 
Назад
Верх