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 consultaset.lvl- nível da consulta, por padrão0
results- objeto com os resultados que devem ser preenchidos e retornados do métodoparse()- 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
resultscontém as chaves das variáveis flat necessárias com o valornone, 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 preenchidoresults.successdeve ser definido como1em 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
overridesao chamar um scraper a partir de outro parathis.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 oprocessConfpode ser executado para cada consulta; neste caso, a lógica pode ser quebrada se oinitdepender 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
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::LinkExtractor