Skip to content

[05] Caso de Uso: Configurações de ações e processamento dinâmico

Breno Matos edited this page May 9, 2023 · 12 revisions

Processamento Dinâmico de Páginas

O coletor desenvolvido conta com a funcionalidade de processamento dinâmico de páginas, isto é, permite coletar páginas após a renderização completa do conteúdo. Isso é necessário visto que, em diversos casos, parte ou a integridade do conteúdo que se deseja obter é apresentado nas páginas apenas após a execução de métodos Javascript.

Essa funcionalidade foi implementada através do Playwright, uma biblioteca Python para automatização de navegadores (Chromium, Firefox e WebKit) através de uma única API. A utilização de um navegador para executar as requisições permite a resolução de problemas complexos, como, por exemplo, realizar coletas em sites que possuem mecanismos bloqueadores de coletas automatizadas, geralmente verificando se a requisição vêm ou não de um navegador.

Configuração de Ações a Serem Executadas nas Páginas

Outra funcionalidade com vistas a expandir a gama de sites coletáveis é o mecanismo de configuração e execução de ações sobre o navegador. Assim, essa funcionalidade foi implementada como uma camada acima do processamento dinâmico.

Essas ações incluem comportamentos tradicionais de um usuário, como cliques em partes da página, como botões e links. Cita-se também a possibilidade de selecionar opções em um “select” ou ainda incluir uma espera de alguns segundos até que algum carregamento seja concluído. Todas essas ações foram desenvolvidas pensando no objetivo de se coletar os dados presentes nas páginas. Por exemplo, muitas vezes é necessário clicar em um botão para que o conteúdo seja devidamente apresentado e, nesse cenário, a ação de “clicar” pode ser usada.

Essas ações podem ser configuradas diretamente pelos usuários ao definir um coletor. Para isso, uma parte da interface web da plataforma de configuração de coletores oferece o controle que se assemelha a uma programação visual. Nessa interface, o usuário pode escolher quais ações deverão ser executadas, quais serão seus parâmetros e pode criar diversas combinações delas para viabilizar a coleta. Um ponto importante é que um dos principais parâmetros dessas ações são expressões XPath, usadas para indicar elementos alvo de uma ação em uma dada página. Portanto, o usuário deve estar familiarizado com essa representação para identificar e informar quais elementos devem ser manipulados em cada uma das ações.

Ações Implementadas

A seguir, apresentamos as principais ações e, para cada uma delas, uma breve explicação de como funcionam, e em quais cenários podem ser usadas. As Figuras 2-7 ilustram a interface para configuração dessas diferentes ações. (Obs: Algumas imagens podem parecer quebrada, basta recarregar a página e elas voltaram a aparecer)

  • Clicar: Essa ação recebe um XPath e é responsável por identificar o elemento correspondente na página e clicar sobre ele. Isso significa que pode ser utilizada em diversas situações, por exemplo, quando se deseja clicar em “Próxima Página” em uma fonte com dados distribuídos em múltiplas páginas, ou ainda quando se deseja clicar em “Expandir Conteúdo”, para que o dado a ser coletado possa ser exibido por completo.

clicar

  • Esperar: Essa ação recebe um valor numérico e é responsável por congelar a execução durante o tempo informado em segundos. É necessário para quando se deseja esperar algum carregamento, ou seja, quando a página ainda está sendo renderizada e o dado ainda não está disponível. Pode ser usado após um “clique”, por exemplo.

esperar

  • Selecionar: Essa ação foi desenvolvida para permitir que o usuário preencha as entradas HTML do tipo “select”. Essas entradas incluem um conjunto de opções que podem ser escolhidas, por exemplo, num formulário de portal da transparência, onde é necessário informar o ano a ser pesquisado. Essa ação recebe como entrada o XPath do “select” e a opção a ser selecionada.

selecionar

  • Para Cada: Essa ação se assemelha à sintaxe de “loops” presentes nas linguagens de programação e foi pensada para auxiliar os usuários a definir um conjunto de ações que deve ser repetido. Assim, quando se deseja iterar pelas páginas de uma fonte, ou clicar em todos os links de uma lista, essa ação é recomendada. Essa ação deve ser combinada (como no screenshot) com outra que, necessáriamente, retorna uma lista, portanto combinações do tipo "Para Cada X em Clique" são inválidas.

para_cada

  • Salvar Página: Essa ação é de extrema importância e permite ao usuário informar quais páginas devem ser salvas ou não. Ou seja, dado que todas as ações já foram feitas e o conteúdo já está disponível, o usuário deve incluir ação de “Salvar Página” para que esse conteúdo seja armazenado em memória e para que, ao final da execução de ações, tais páginas possam ser armazenadas em disco. Não é necessário informar qualquer parâmetro. Além disso, essa ação, quando usada dentro de um loop do tipo "Para Cada", irá salvar cada uma das páginas encontrada nesse loop, ou seja, é possível salvar multiplas páginas dado que essa ação foi executada diversas vezes. Ao final da execução, além de armazenadas em disco, essas páginas podem ser exploradas com as outras ferramentas presentes na plataforma, por exemplo, a exploração de links, o que permite uma configuração mais complexa e a combinação do mecanismo de processamento dinâmico com outros. Contudo, é importante lembrar que, a partir desse ponto, novas requisições serão executadas fora de um webdriver, portanto, podem não irão carregar mais o conteúdo JavaScript da página.

salvar_pagina

  • Voltar: Simula a opção de voltar dos navegadores. Não é necessário informar qualquer parâmetro. Essa ação deve ser usado quando alguma outra ação altera a página e, para continuar a execução, é necessário retornar a anterior e continuar outros processamentos. Ou seja, é importante considerar o estado das páginas ao configurar coletores com ações, caso contrário poderão apresentar comportamento inesperado.

voltar

  • Imprimir: Essa ação tem como objetivo ajudar o programador. Essa ação se assemelha ao "print" do Python, e permite imprimir nos logs dos coletores qualquer valor desejado, por exemplo, XPath armazenado em uma variável.

imprimir

  • Localizar Elementos: Essa ação é responsável por receber um XPath genérico (que apresenta um asterisco) e retornar todos os elementos na página que casam com esse elemento, semelhante à sintaxe de asterisco no Bash. Com isso, podemos iterar nesses elementos, usando o "Para Cada" e possivelmente, manipular cada uma deles, por exemplo, com um clique. É importante lembrar que o XPath deve ter obrigatoriamente um e apenas um asterisco. Além disso, essa ação deve ser usada necessariamente junto da ação de “Para Cada”.

localizar_elementos

  • Opções: Essa ação é responsável por receber um XPath de um select e retornar todas as opções listadas nele. Com isso, podemos iterar nessas opções, usando o "Para Cada" e possivelmente, selecionar cada uma delas, usando o "Selecione". Diferente do "Localiza Elementos", essa ação recebe o XPath de um tipo específico de elemento (Selects) e retorna uma lista de valores (e não de outros XPaths). Isso significa que essa ação deve ser usada necessariamente junto da ação de “Para Cada”.

opcoes

  • Digitar Em: Essa ação foi desenvolvida para permitir que o usuário preencha as entradas HTML do tipo “input” para entradas textuais. Essas entradas permitem que o usuário digite uma sequência de caracteres, por exemplo, numa caixa de busca, onde é necessário informar algum nome a ser pesquisado. Essa ação recebe como entrada o XPath do elemento e o texto a ser digitado.

digitar_em

  • Repetir: Essa ação recebe um valor inteiro N e é responsável por retornar a lista de valores partindo de 0 até N-1. Com essa ação, pode-se definir a repetição de eventos, como vários cliques seguidos ou várias esperas. Isso significa que essa ação deve ser usada necessariamente junto da ação de “Para Cada”, como pode ser visto no screenshot abaixo.

repetir

  • Objeto: Pode ser utilizado em conjunto com outro passo para retornar um objeto estático. Exemplo: pode ser utilizado na função de Para Cada para retornar uma lista de valores pré-definidos.

objeto

  • Atribuição: Atribui o valor de retorno de um dos passos ao nome fornecido. A partir dai, este nome pode ser utilizado em outros passos em que este valor será útil (e.g. pode se atribuir o retorno da função Object, e utiliza-lo na função de Para Cada).

atribuicao

  • Extrair Texto de: Extrai e retorna o texto do elemento apontado pelo xpath fornecido. É útil em casos em que alguma informação da página é útil para a coleta (e.g. número total de páginas em uma lista). Dica: pode ser mais útil se utilizado com o passo de Atribuição, como no exemplo abaixo. Nota: Como o retorno da função é um texto, é necessário converter esse valor para um valor inteiro antes que ele possa ser utilizado no para cada. Futuramente essa conversão será feita por um passo separado, mas por ora, pode ser utilizada a função int() do python para isso.

extrair_texto_de

  • Abrir em Nova Aba: Este passo funciona de forma parecida a função de clique, com a diferença de que aqui, caso o link apontado pelo xpath fornecido leva a uma página de destino, ela é aberta em uma nova aba, e o contexto de navegação é alterado para esta nova aba. A utilidade deste passo surge em situaçoes em que o passo de retorna página não pode ser usado para ir e voltar das páginas da coleta. Um exemplo de um caso desses, seria uma página que contem um formulário que tem seus resultados recarregados na açao de retornar a pagina, logo apos um resultado ser clicado. Utilizando a função de nova aba, a página do formulario poderia ser mantida aberta, enquanto cada item do resultado pode ser aberto em uma nova aba.

abrir_em_nova_aba

  • Comparação:

comparacao

  • Checar se elemento existe na página

Recebe um xpath e checa se o elemento especificado existe na página

checar_se_elemento

  • É clicável

Checa se o elemento especificado no campo 'xpath' é clicável

e_clicavel

  • Está escrito

Checa se um texto está escrito no elemento especificado no campo 'xpath'

esta_escrito

  • Quebrar captcha de imagem

quebrar_captcha_de

  • Executar código javascript

Permite a execução de código javascript na página, basta colar o código no campo à esquerda.

codigo_javascript

  • Executar em iframe

Permite a exeução de passos dentro de um iframe. Recebe o xpath de um iframe

executar_em_iframe

  • Screenshot

Realiza a captura de tela (screenshot) da página.

screenshot

  • Enquanto

Um passo condicional que permite escolher uma ação para realizar, ENQUANTO um elemento está presente na página. As escolhas de ações estão disponíveis no menu drop-down à direita, aqui representadas pela opçao 'Clicar'

enquanto

  • Se

Um passo condicional que permite escolher uma ação para realizar, dada a presença de um elemento na página. As escolhas de ações estão disponíveis no menu drop-down à direita, aqui representadas pela opçao 'Clicar'

se

Observações gerais

Essa funcionalidade está em desenvolvimento atualmente, por isso, pode apresentar bugs e comportamentos inesperados durante a execução. Além disso, assim como nas linguagens de programação, nem toda combinação de ações é válida (por exemplo, clicar num XPath inválido ou combinar "Para Cada" com "Imprime"), por conta disso, é necessário atenção.

Em relação aos dados de entrada das ações, a solução precisa diferenciar strings de outras entradas, por exemplo, variáveis, por conta disso, parâmetros textuais (como XPaths puros ou texto) devem ser informados usando aspas, como pode ser visto nos exemplos abaixo. Contudo, caso o valor seja um inteiro (como tempo de espera), não é necessário usá-las. Por fim, variáveis (iteradoras, por exemplo), também não exigem aspas por não representarem textos.

Para garantir que a configuração faça sentido e funcionará, é recomendável executar parte dela manualmente, isto é, executar em um navegador aberto as ações que seriam feitas internamente. Nesse sentido, pode-se fazer, por exemplo, uma sequência de cliques ou alteração no valor dos selects e observar o comportamento da página. Tudo que acontecerá no navegador, acontecerá internamente!

Além disso, é necessário ter alguma familiaridade com XPaths e código fonte de páginas da web para conseguir configurar corretamente as ações e seus valores. Por isso, é recomendado estudar essas funcionalidade, e alguns links podem ajudar, em especial esse sobre XPath e esses sobre as ferramentas de inspecção do Chorme e inspecção no Firefox, respectivamente. Caso você utilize outro navegador, poderá encontrar ferramentas parecidas, pois todos os navegadores oferecem suporte para esse tipo de funcionalidade.

Por fim, assim como na programação tradicional, essa funcionalidade possui uma componente relacionada a criatividade! Portanto, para uma só fonte, é possível criar diferentes configurações válidas e que coletarão os dados desejados.

Configurando um coletor

Para testar essa funcionalidade, vamos testar um coletor que utiliza uma combinação dessas ações para ser executado. A fonte alvo será Licitações de Uberaba, com o seguinte URL: http://www.uberaba.mg.gov.br/licitacoes/pmu.html.

Um screenshot da página pode ser visto abaixo:

image

Nessa página, vamos baixar todos os arquivos listados com os respectivos ícones. Para isso, devemos iterar por todos os anos, no select acima e, dentro de cada ano, devemos iterar em todas as páginas, no select em baixo. Mais detalhes de como fazer isso com ações estão abaixo.

Inicialmente, precisamos configurar as informações básicas do coletor. Nesse caso, estou chamando o coletor de "Licitações de Uberaba", para identificá-lo, além disso, estou informando um diretório válido no meu computador para armazenar os dados. Por fim, é importante lembrar que a URL deve ser passada nessa etapa, e nesse caso, usamos a URL: http://www.uberaba.mg.gov.br/licitacoes/pmu.html, que foi apresentada anteriormente.

image

Em seguida, para ativarmos a funcionalidade de processamento dinâmico, é preciso selecionar o checkbox "Processamento Dinâmico" na aba "Processamento dinâmico". O screenshot abaixo ilustra essa seleção. Nessa aba, podemos selecionar diferentes navegadores web, resolução do navegador, além de inserir passos de uma coleta via json.

image

Ao final, devemos informar as ações. Abaixo está a configuração usada para essa fonte.

image

Para reproduzir a coleta, também é possível inserir o json abaixo no campo 'JSON dos passos'

{"step":"root","depth":0,"children":[{"step":"espere","depth":1,"arguments":{"segundos":"15"}},{"step":"para_cada","depth":1,"iterator":"ano","children":[{"step":"selecione","depth":2,"arguments":{"xpath":"'/html/body/table[2]/tbody/tr/td/table/tbody/tr[1]/td/table/tbody/tr[2]/td/table/tbody/tr[2]/td[4]/select'","opcao":"ano"}},{"step":"espere","depth":2,"arguments":{"segundos":"10"}},{"step":"para_cada","depth":2,"iterator":"pagina","children":[{"step":"selecione","depth":3,"arguments":{"xpath":"'/html/body/table[2]/tbody/tr/td/table/tbody/tr[4]/td/table/tbody/tr/td/table/tbody/tr/td[2]/select'","opcao":"pagina"}},{"step":"espere","depth":3,"arguments":{"segundos":"10"}},{"step":"para_cada","depth":3,"iterator":"elemento","children":[{"step":"clique","depth":4,"arguments":{"elemento":"elemento"}}],"iterable":{"call":{"step":"localiza_elementos","arguments":{"xpath":"'/html/body/table[2]/tbody/tr/td/table/tbody/tr[2]/td/table/tbody/tr[*]/td/table/tbody/tr/td[4]/table/tbody/tr/td[4]/img'"}}}}],"iterable":{"call":{"step":"opcoes","arguments":{"xpath":"'/html/body/table[2]/tbody/tr/td/table/tbody/tr[4]/td/table/tbody/tr/td/table/tbody/tr/td[2]/select'"}}}}],"iterable":{"call":{"step":"opcoes","arguments":{"xpath":"'/html/body/table[2]/tbody/tr/td/table/tbody/tr[1]/td/table/tbody/tr[2]/td/table/tbody/tr[2]/td[4]/select'"}}}}]}

Obs: Caso necessário, abra a imagem em outra aba para conseguir ampliá-la e torná-la mais legível. Para entender melhor essa configuração, abaixo, está uma explicação de cada uma das partes:

  • "Espera": É necessário esperar um tempo para começar as ações, pois o site é carregado nesse tempo e os elementos ficam acessíveis apenas após esse carregamento
  • "Para Cada" e "Opções": nesse ponto, a ação de opções retorna uma lista com todos os valores do select, aqui, os select de ano. Seu parâmetro é o XPath do select na página, que pode ser acessado através das ferramentas de inspecionar dos navegadores. Essa ação está sendo usada dentro da ação de "Para Cada", pois esse último é o responsável por receber uma lista e iterar por ela. A variável iteradora foi chamada de "ano" e pode ser acessada ao longo do código
  • "Selecione": essa ação está identada em relação a anterior, o que significa que irá ser executada em cada iteração do "Para Cada". Seu objetivo é manipular o select e definir seu valor. O XPath é o mesmo do Opções, pois, estamos apontados para o mesmo elemento, mas em ações distintas. O valor a ser selecionado está armazenado na variável "ano" definida antes, por isso, podemos usá-la como parâmetro nesse ponto.
  • "Espera": nesse site, cada seleção gera um recarregamento de página, por causa disso, é necessário esperar um tempo para começar as novas ações. Esse tempo foi definido ao observar experimentalmente a página
  • "Para Cada" e "Opções": novamente, nesse ponto, usamos a ação de Opções para retornar uma lista com todos os valores do select, aqui, os select de páginas. Seu parâmetro é o XPath do select de paginação, que também pode ser acessado através das ferramentas de inspecionar dos navegadores. Essa ação está sendo usada dentro da ação de "Para Cada", pois esse último é o responsável por receber uma lista e iterar por ela. A variável iteradora foi chamada de "pagina" e pode ser acessada ao longo do código
  • "Selecione": essa ação está identada em relação a anterior, o que significa que irá ser executada em cada iteração do "Para Cada". Seu objetivo é manipular o select e definir seu valor. O XPath é o mesmo do Opções, pois, estamos apontados para o mesmo elemento, mas em ações distintas. O valor a ser selecionado está armazenado na variável "ano" definida antes, por isso, podemos usá-la como parâmetro nesse ponto.
  • "Espera": nesse site, cada seleção gera um recarregamento de página, por causa disso, é necessário esperar, novamente, um tempo para começar as novas ações. Esse tempo foi definido ao observar experimentalmente a página. Além disso, mantemos a identação anterior
  • "Para Cada" e "Localiza Elementos": nesse ponto, usamos a ação de "Localiza Elementos" para retornar uma lista com todos os elementos na página que casam com um determinado XPath. Seu parâmetro é o XPath genérico de elementos, que envolve um asterisco, que também pode ser acessado através das ferramentas de inspecionar dos navegadores. Mais especificamente esse asterisco indica "todos", assim, todo e qualquer elemento que tiver um caminho possível será retornado. Essa ação está sendo usada dentro da ação de "Para Cada", pois esse último é o responsável por receber uma lista e iterar por ela. A variável iteradora foi chamada de "elemento" e pode ser acessada ao longo do código
  • "Clique": Com a variável "elemento" definida, podemos identificar cada um dos arquivos a serem baixados. Para disparar esse download, é necessário clicar nesses elementos, por isso, essa última ação é usada, que recebe um XPath, nesse caso, armazenado na variável "elemento".

É importante observar a identação dos blocos de ações, essa informação é importante para manter corretamente os fluxos de execução. Por exemplo, como desejamos coletar todas as páginas para cada um dos anos, é necessário repetir a iteração de página em cada iteração de ano, e essa repetição é indicada através da identação. Além disso, é necessário que o sistema seja consistente, ou seja, se existem comportamentos distintos em páginas distintas (como mudanças de XPath), haverá erros durante a execução, pois, por exemplo, um elemento pode não ser encontrado. Nesse caso, antes de configurar um coletor, é desejável fazer uma exploração profunda da página e de seus comportamentos, além disso, recomenda-se reproduzir as primeiras ações do coletor manualmente, para validar a configuração pensada.

Ao final, teremos o coletor desejado, e podemos executá-lo!