Pular para o conteúdo principal

Métodos Hook

Estes métodos funcionam segundo o princípio de hooks. A implementação destes métodos permite controlar o funcionamento do scraper em diferentes etapas, desde a inicialização até à destruição do objeto

A implementação de todos os métodos, exceto o parse, é opcional

async parse(set, results)

O método parse implementa a lógica principal de processamento da consulta e obtenção do resultado da extração de dados, sendo passados como argumentos:

  • set - objeto com informações sobre a consulta:
    • set.query - string de texto da consulta
    • set.lvl - nível da consulta, por padrão 0
  • results - objeto com os resultados que devem ser preenchidos e retornados do método parse()
    • o scraper deve verificar a existência de cada chave no objeto results e preenchê-la apenas se estiver presente, otimizando assim a velocidade e extraindo apenas os dados que são utilizados na formação do resultado
    • results contém as chaves das variáveis flat necessárias com o valor none, o que por padrão significa que o resultado não foi obtido, bem como as chaves de variáveis de matriz (arrays) com o valor de um array vazio, pronto para ser preenchido
    • results.success deve ser definido como 1 em caso de processamento bem-sucedido da consulta, por padrão o valor é 0, indicando que a consulta foi processada com erro

Vejamos um exemplo:

class JS_HTML_Tags extends BaseParser {
static defaultConf = {
results: {
flat: [
['title', 'Title'],
],
arrays: {
h2: ['H2 Headers List', [
['header', 'Header'],
]],
}
},
...
};

async parse(set, results) {
// Obtemos o conteúdo da página HTML, cujo endereço foi passado na consulta
const {success, data, headers} = await this.request('GET', set.query);

// Verificamos o sucesso e o tipo de data; no processamento correto de páginas HTML devemos receber o tipo 'string', caso contrário o A-Parser retorna um objeto do tipo Buffer
if (success && typeof data == 'string') {
let matches;

// Verificamos a necessidade de coletar o title e salvamos o valor
if (results.title && matches = data.match(/<title[^>]*>(.*?)<\/title>/))
results.title = matches[1];

// Verificamos a necessidade de coletar h2
if (results.h2) {
let count = 0;
const re = /<h2[^>]*>(.*?)<\/h2>/g;
while(matches = re.exec(data)) {
// Salvamos em loop todas as tags h2 encontradas
results.h2.push(matches[1]);
}
}

// Notificamos sobre o sucesso da extração de dados
results.success = 1;
}

// Retornamos os resultados processados
return results;
}
};

Note que você pode criar suas próprias funções e métodos para uma melhor organização do código:

function Answer() {
return 42;
}

class JS_HTML_Tags extends BaseParser {
...

async parse(set, results) {
results = await this.doWork(set, results);
return results;
}

async doWork(set, results) {
results.answer = Answer();
return results;
}
};

async processConf?(conf)

Este método é utilizado para transformar a configuração de acordo com certas regras, por exemplo, ao usar captcha, precisamos sempre usar sessões:

async processConf(conf) {
if (conf.useCaptcha)
conf.useSessions = 1
}

async parse(set, results) {
if (conf.useSessions)
await this.login();
}

A existência deste método deve-se ao fato de que o A-Parser suporta campos de configuração dinâmicos e, dentro de uma mesma tarefa, a configuração pode ter valores diferentes; tal cenário é possível em dois casos:

  • Uso de modelos nos campos de configuração, por exemplo [% tools.ua.random() %] para o campo User-Agent
  • Uso de overrides ao chamar um scraper a partir de outro para this.parser.request

O método processConf é chamado uma única vez antes do init(). Para os casos descritos acima, o processConf é chamado adicionalmente antes do processamento de cada consulta

Regras principais para a aplicação do processConf:

  • Use apenas se as transformações da configuração tiverem efeito no desempenho
  • Tenha em mente que o init é executado uma vez, enquanto o processConf pode ser executado para cada consulta; neste caso, a lógica pode ser quebrada se o init depender de campos de configuração que se alteram (veja abaixo)

async init?()

O método init é chamado uma vez na inicialização do objeto base do scraper, servindo para realizar ações únicas:

  • Iniciar o navegador
  • Inicialização do gerenciador de sessões com o método this.sessionManager.init()
  • Conexão ao banco de dados e criação de tabelas no BD
  • Leitura de dados estáticos
  • E assim por diante
aviso

Como o método é chamado apenas uma vez, todos os campos de configuração dos quais o init() depende não podem ser usados em conjunto com modelos de campos de configuração ou com overrides ao chamar this.parsers.request

async destroy?()

O método destroy é chamado uma vez ao finalizar o trabalho da tarefa, sendo necessário para a destruição correta de recursos abertos:

  • Fechamento do navegador
  • Fechamento da conexão com o BD
  • E assim por diante

async threadInit?()

Este método é iniciado na inicialização de cada thread; cada thread representa uma cópia do objeto base do scraper com seu próprio this.threadId único, que começa em 0 e termina em threads_count - 1

Principais variantes de aplicação:

  • criação de uma página (aba) do navegador para cada thread

async threadDestroy?()

Executado ao finalizar a thread durante o processo de conclusão da tarefa, serve para liberar recursos alocados para esta thread

async afterResultsProcessor?(results)

Este método é executado após o processamento dos resultados: pelo construtor de resultados, filtragem e desduplicação. O principal caso de uso é adicionar consultas à fila usando o método this.query.add após a aplicação de filtros de usuário; desta forma, a filtragem de links para navegação (followlinks) é implementada para o scraper HTML::LinkExtractorHTML::LinkExtractor