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

Тема в разделе "Техническая поддержка", создана пользователем Forbidden, 11 дек 2016.

  1. Forbidden

    Forbidden Administrator Команда форума A-Parser Enterprise

    Некоторые факты:
    • Используя всю мощь A-Parser теперь можно написать свой парсер/регер/постер со сколько угодно сложной логикой
    • Для написания кода используется JavaScript с возможностями ES6(движок v8, обзор базовых возможностей ES6)
    • Код парсеров максимально лаконичен, позволяет сосредоточится на написании логики; работу с многопоточностью, сетью, прокси, результатами, логами и т.д. A-Parser берет на себя
    • Код можно писать прямо в интерфейсе парсера, добавив новый парсер в Редакторе парсеров, по умолчанию будет загружен простой пример, на основе которого можно быстро приступить к созданию собственного парсера
    • Доступно для лицензий Pro и Enterprise, для всех ОС кроме linux 32bit

    Пример 1 - Парсинг HTML тега title на произвольной странице:
    [​IMG]
    Результат:
    Код:
    https://a-parser.com/: A-Parser - парсер для профессионалов SEO
    Код:
    class Parser {
        constructor() {
            this.defaultConf = {
                results: {
                    flat: [
                        ['title', 'HTML title'],
                    ]
                },
                results_format: '$query: $title\\n',
                parsecodes: {
                    200: 1,
                },
                max_size: 200 * 1024,
            };
        }
    
        *parse(set, results) {
            this.logger
                && this.logger.put("Start scraping query: " + set.query);
    
            let response = yield this.request('GET', set.query, {}, {
                check_content: ['<\/html>'],
                decode: 'auto-html',
            });
    
            if(response.success) {
                let matches = response.data.match(/<title>(.*?)<\/title>/i);
                if(matches)
                    results.title = matches[1];
            }
       
            results.success = response.success;
    
            return results;
        }
    }
    
    • В конструкторе задаются основные параметры парсера: собираемые результаты, формат результатов, успешный код HTTP ответа, и ограничение по размеру загружаемой страницы
    • В функции парсинга используются следующие возможности:
      • Логирование процесса работы
      • Получение данных по HTTP протоколу, указывается метод, url(запрос), дополнительно указана проверка контента и автоматическое определение кодировки страницы. Работа с прокси, количество попыток и прочие параметры задаются стандартными настройками в интерфейсе парсера
      • Проверка ответа, с помощью регулярного выражения парсится тег title и возвращается результат
    Пример 2 - Получение подсказок по запросу, затем сбор первой ссылки с Google по каждой подсказке:
    [​IMG]

    Результат:
    Код:
    buy buy baby: https://www.buybuybaby.com/ (<b>Buy Buy Baby</b>)
    buy here pay here: https://en.wikipedia.org/wiki/Buy_Here_Pay_Here (<b>Buy Here Pay Here</b> - Wikipedia)
    buy: http://www.rakuten.com/ (Rakuten.com - Computers, Electronics, Apparel, Home, Sporting ...)
    buy me a boat: http://www.azlyrics.com/lyrics/chrisjanson/buymeaboat.html (CHRIS JANSON LYRICS - <b>Buy Me A Boat</b> - A-Z Lyrics)
    buy buy baby coupon: https://www.retailmenot.com/view/buybuybaby.com (20% Off <b>buybuy BABY Coupon</b>, Free Shipping 2016 - RetailMeNot)
    buying a house: http://www.wikihow.com/Buy-a-House (How to <b>Buy a House</b>: 9 Steps (with Pictures) - wikiHow)
    buy used cars: http://www.autotrader.com/car-topics/used-car-buying.xhtml (<b>Buying</b> a <b>Used Car</b> - <b>Used Car</b> Reviews &amp; News, Compare Used ...)
    buy kratom: http://www.buykratom.us/ (<b>Buy Kratom</b> | Purveyors of Premium Kratom | Get Kratom by Kratora™)
    buy instagram followers: https://www.instabuyagram.com/instagram-followers/ (<b>Buy Followers</b> For <b>Instagram</b> Today at $1.88 | Fast &amp; Safe ...)
    buy sell trade: https://www.buysaleandtrade.com/ (Classified Ads Online that <b>Buy Sell Trade</b> | BuySaleandTrade.com)
    Код:
    class Parser {
        constructor() {
            this.defaultConf = {
                results: {
                    arrays: {
                        serp: ['Top1 list', [ ['suggest', 'Suggest'], [ 'link', 'Link' ], [ 'anchor', 'Anchor' ] ] ],
                    }
                },
                results_format: "$serp.format('$suggest: $link ($anchor)\\n')",
                SE_Google_Suggest_preset: 'default',
                SE_Google_preset: 'default',
            };
       
            this.editableConf = [
                ['SE_Google_Suggest_preset', ['combobox', 'SE::Google::Suggest preset']],
                ['SE_Google_preset', ['combobox', 'SE::Google preset']],
            ];
        }
    
        *parse(set, results) {
            let result = yield this.parser.request('SE::Google::Suggest', this.conf.SE_Google_Suggest_preset, set.query);
       
            if(result.info.success) {
                let suggests = result.results;
                this.logger.put('Total grabbed ' + suggests.length + ' suggests');
    
                for(const suggest of suggests) {
                    result = yield this.parser.request('SE::Google', this.conf.SE_Google_preset, {pagecount: 1, linksperpage: 10}, suggest);
                    results.serp.push(suggest, result.serp[0], result.serp[1]);
                }
            }
       
            results.success = result.info.success;
    
            return results;
        }
    }
    
    • В конструкторе задаются названия пресетов для парсеров SE::Google::Suggest SE::Google::Suggest и SE::Google SE::Google, при этом выбор будет доступен в интерфейсе, в настройках парсера JS::Google::FromSnippets
    • В функции парсинга у нас нет вызова HTTP запросов, вместо этого мы напрямую обращаемся к существующим парсерам:
      • Получаем список подсказок по запросу
      • Затем по каждой подсказке в цикле получаем результаты первой страницы выдачи Google, сохраняем в наш результат подсказку и только первую ссылку с анкором

    Пример 3 - авторизация и парсинг MOZ.com
    [​IMG]
    Результат:
    Код:
    a.com - DA: 65; PA: 71; Spam Score: -
    y.com - DA: 42; PA: 51; Spam Score: -
    k.com - DA: 36; PA: 44; Spam Score: -
    aa.com - DA: 90; PA: 73; Spam Score: -
    z.com - DA: 49; PA: 57; Spam Score: -
    v.com - DA: 34; PA: 42; Spam Score: -
    l.com - DA: 42; PA: 51; Spam Score: -
    ab.com - DA: 57; PA: 64; Spam Score: 1
    ae.com - DA: 78; PA: 63; Spam Score: -
    
    Код:
    let session;
    
    class Parser {
        constructor() {
            this.defaultConf = {
                results: {
                    flat: [
                        ['da', 'Domain Authority'],
                        ['pa', 'Page Authority'],
                        ['ss', 'Spam Score'],
                    ]
                },
                results_format: '$query - DA: $da; PA: $pa; Spam Score: $ss\\n',
                parsecodes: {
                    200: 1,
                },
                max_size: 200 * 1024,
                login: [email protected]',
                password: 'qqq111',
            };
        }
    
        *parse(set, results) {   
            yield this.mutex.lock();
            if(!session) { //get session in one thread to share it for all
                let response = yield this.request('POST', 'https://moz.com/login', {
                    'data[User][login_email]': this.conf.login,
                    'data[User][password]': this.conf.password,
                });
    
                if(response.success && response.data.match(/<title>Home - Moz/)) {
                    //login ok
                }
                else {
                    this.logger.put('Invalid account');
                    results.success = 0;
                    yield this.mutex.unlock();
                    return results;
                };
                session = this.cookies.getAll();
            };
            yield this.mutex.unlock();
          
            this.cookies.setAll(session);
          
            let response = yield this.request('GET', 'https://moz.com/researchtools/ose/api/comparisons', {
                site: set.query
            });
              
    
            if(response.success) {
                let json = JSON.parse(response.data);
                results.da = json.data.root_domain[0].domain_authority ? Math.round(json.data.root_domain[0].domain_authority) : '-';
                results.pa = json.data.page[0].page_authority ? Math.round(json.data.page[0].page_authority) : '-';
                results.ss = json.data.subdomain[0].spam_score || '-';
            }
          
            results.success = response.success;
    
            return results;
        }
    }
    
    • Используем мьютекс для авторизации в один поток
    • Затем передаем сессию для всех потоков используя внешнюю переменную
    • Разбираем JSON встроенными средствами

    Документация
    JS парсеры на данный момент в процессе частых изменений и добавления функционала, документация будет собираться в этом топике, после чего будет добавлена в общую документацию по A-Parser'у

    1. Общие принципы работы
    • Конструктор вызывается однократно для каждого задания
      • Необходимо обязательно задать this.defaultConf.results и this.defaultConf.results_format, остальные поля необязательны и будут принимать значения по умолчанию
      • Массив this.editableConf определяет какие настройки могут быть изменены пользователем из интерфейса A-Parser
    • Метод *parse представляет собой генератор, и на любую блокирующую операцию должен возвращать yield(это основное и единственное отличие от обычной функции)
      • Метод вызывается для каждого запроса поступившего в обработку
      • Передается query(запрос) и results(пустая заготовка для результатов)
      • Необходимо обязательно вернуть заполненый results, предварительно выставив флаг success
    2. yield this.request
    • Получение HTTP ответа по запросу, в качестве аргументов указывается method, url, хэш с query параметрами, хэш с опциями
    3. yield this.parser.request
    • Получение результатов от другого парсера, в качестве аргументов указывается название парсера, его пресет, хэш override(опционально), запрос
    4. tools.*
    • Глобальный объект tools, позволяет получить доступ к встроенным функциям A-Parser'а, а также к tools.js
    5. this.logger
    • Метод this.logger.put отображает строчку в логе
    • this.logger.doLog может использоваться как флаг для оптимизации, для случаев когда лог не ведется и аргументом к .put идет сложное выражение
    6. yield this.sleep(sec)
    • Устанавливает задержку в потоке на число секунд, может быть дробным
    7. yield this.mutex.lock(), yield.this.mutex.unlock()
    • Мютекс для синхронизации между потоками, позволяет заблокировать секцию кода для одного потока, пример в парсере JS::Rank::MOZ
    8. this.cookies.getAll(), this.cookies.setAll(cookies)
    • Получение и установка cookies
    TODO:
    • Улучшения редактора(создание файлов, подсветка не сохраненных изменений)
    • Работа с файлами и аккаунтами из парсеров(для файлов использовать node-like api)
    • Экспорт\импорт парсеров

    Вступайте в Skype чат для разработчиков JS парсеров: https://join.skype.com/nMAYI9lpsJ9Z
    Первый пост будет постоянно обновляться, в комментах предлагаю вести обсуждение
     
    Последнее редактирование: 26 дек 2016
    Metroid, vipuncle, Support и 6 другим нравится это.
  2. Forbidden

    Forbidden Administrator Команда форума A-Parser Enterprise

    • Добавлен пример парсинга Moz.com с авторизацией, парсер сделан на основе этого пресета
    • Добавлены описания мьютексов, работы с куками, и sleep
    • Начиная с версии 1.1.712 query заменять на хэш set который содержит все элементы запроса(запрос, первый запрос, уровень, дополнительные поля и т.п.), для доступа к запросу в текстовом виде теперь необходимо использовать set.query
     
    LmPopo и relay нравится это.

Поделиться этой страницей