Capítulo 4
Modelos de web crawling
Resumo
Neste capitulo, o objetivo é construir um crawler que seja organizado e escalável. Para isso, primeiramente devemos nos atentar as entradas e aos dados que queremos obter. Para isso, utilizaremos web crawlers que coletam um número limitado de dados por página, pois não lidaremos com banco de dados.
Planejando e definindo objetos
Sempre que pensamos em obter determinado dado, buscamos sites específicos e nos baseamos neles, resultando em novos dados a cada página visitada e um conjunto difícil de interpretar. Para construir um crawler eficiente, é preciso considerar os aspectos mais gerais de cada 'objeto' e buscar obter apenas o que será necessário para sua aplicação.
Lidando com diferentes layouts
Sabendo que é preciso lidar com diversos sites com estruturas diferentes, o jeito mais óbvio de obter esses dados é produzir um crawler ou um parser de página específico para cada um. No entanto, essa abordagem deixa de ser eficiente no momento em que você precisa escalar seu código.
Caso opte por esse caminho, será possível observar um certo padrão na função de cada parser, pois todos possuem o objetivo de obter o mesmo dado. Por exemplo, se busca-se capturar o título, data de publicação e o primeiro parágrafo de sites de notícias, pode-se perceber que as únicas mudanças necessárias para obter esses dados é a sua localização na determinada página. Para isso, consegue-se criar uma função genérica o suficiente para que receba essa posição e retorne o dado.
Neste capítulo, será introduzido a função 'select' de um objeto BeautifulSoup. Tal função, realiza a busca de determinada tag que contenha o seletor CSS especificado.
Em CSS, para selecionar determinada classe, utiliza-se '.nomeClasse'. A função select exigirá o mesmo padrão de argumento. Se o objetivo é selecionar apenas a tag 'a' com a classe 'Paragrafo', utilizamos:
Essa função retornará uma lista com todas as correspondências encontradas.
Estruturando os crawlers
Esta seção tem o objetivo de exemplificar uma estrutura capaz de coletar dados e links de maneira automatizada. O crawler que será apresentado é um bom começo para os que você irá construir a partir de agora, contemplando a maioria dos problemas que você encontrará, salvo algumas mudanças.
Rastreando os sites por meio de pesquisas
O modo mais prático de encontrar sites é pesquisando. Embora seja necessário uma palavra-chave ou termo específico para haver uma pesquisa eficiente, a maioria dos sites possuem uma página de busca com um link base concatenado com algumas outras informações, como por exemplo, "https://example.com?search=meuTopico".
Dentro da página, o link pode ser relativo ("/articles/page.html") ou absoluto ("https://example.com/articles/page.html"). Essa propriedade será armazenada na estrutura criada para o website.
Após a pesquisa, grande parte dos sites mantém os resultados em uma estrutura de fácil indentificação, em geral com um tag conveniente ao redor, como <span class='Result'>
, cujo formato também será armazenado.
Primeiramente, o código possuirá uma classe denominada Content, que será a base de identificação para todos os sites/artigos.
Cada objeto dessa classe armazenará o URL, o corpo da página HTML (body), seu título e o tópico que gerou sua pesquisa.
Já, a classe Website, será criada para que seja possível armazenar todos os dados referentes a estrutura do site e ao modo como a pesquisa deve ocorrer. Os atributos são:
name: Nome da página
url: Link para acessar a site
searchUrl: Link base da página de pesquisa do site
resultListing: Define o "local" em que estão armazenados os resultados da pesquisa na página de busca
resultUrl: Define o "local" exato em que está o URL do item pesquisado em resultListing
absoluteUrl: Indica se o resultUrl é absoluto ou não
titleTag: Título da página web
bodyTag: Body da página web
Vale lembrar que o "local" será buscado por uma função select.
Agora será apresentado a classe Crawler, ela será capaz de realizar as buscas automatizadas a partir dos sites inserido pelo usuário. A classe possui uma função que faz o acesso a página e retorna um objeto BeautifulSoup (getPage). Um outro método que faz retorna o texto de determinada tag a partir de um seletor (safeGet). O método de pesquisa, que irá realizar a busca de determinado tema na página e, após fazer o acesso, buscará todos os itens que forem apresentados, recuperando seus determinados URLs. Por fim, irá recuperar o título e o body da página resultante.
Durante a execução, esse script percorre os itens da lista topics e, pra cada topico, fará a busca em cada site presente em siteData. Em seguida, rastreia cada informação apresentada anteriormente e, caso ocorra tudo corretamente, os dados base de cada página serão exibidos no console. Um exemplo, executado durante a produção deste gitbook se apresentou no seguinte formato:
Explicando o teste
Para o exemplo, foi utilizado o site da empresa Livrarias Curitiba. Para isso, foram informados, respectivamente, seu URL (https://www.livrariascuritiba.com.br/), URL de busca que terá o tópico concatenado (https://www.livrariascuritiba.com.br/), tag+seletor de onde se encontram os resultados da busca (li.livros), tag+seletor de onde se encontra o URL - na página de busca - para cada item resultante (a.productImage), booleano referente ao modelo do URL encontrado (True), tag+seletor onde está o título da página (h1 div.productName) e tag+seletor de onde se localiza a descrição do produto (div.productDescription).
Essa estruturação dos laços de repetição, buscando a mesma página para cada tópico em momentos diferentes, foi utilizada para evitar uma sobrecarga no servidor. Pois, caso houvessem centenas de tópicos a serem buscados, e os laços estivessem invertidos, também seriam realizados centenas de acessos. Se atentar a esse ponto durante a produção de seus web crawlers é de fundamental importância.
Rastreando sites por meio de links
Os mesmos conceitos vistos no Capítulo 3 podem ser usados de maneira mais flexível nessa seção, criando um Web Crawler capaz de seguir qualquer link que corresponda a um padrão específico de URL. Esse tipo de Web Crawler é usado para coletar todos os dados de um site, não apenas os específicos, além das páginas desorganizadas ou dispersas.
Esses tipos de crawlers não exigem um método estruturado para localizar links, portanto atributos que descrevem detalhes sobre a página não são necessários no objeto Website. Apesar disso, é necessário seguir regras sobre os tipos de página que serão selecionados. Usaremos um targetPattern (Expressão regular para os URLs visitados) e a variável absoluteUrl, já vista anteriormente. O script a seguir percorre os links da página escolhida e seleciona os que correspondem à eventos:
Segue abaixo o exemplo do resultado da execução desse código:
Explicando o teste
Para esse exemplo, foi utilizado o site do ICMC. Nesse caso, atributos parecidos com o teste anterior foram utilizados, porém nesse caso um padrão regex é adicionado e ele será utilizado para fazer uma seleção daqueles links que correspondem às páginas de eventos, identificadas pelo endereço: 'https://www.icmc.usp.br/eventos/'. Dessa forma ele percorre todos esses links e apenas coleta o título (div.page-header), e sua descrição (div.noticias-texto). Nesse caso, Website é uma propriedade do objeto Crawler e isso implica uma abordagem voltada para o armazenamento das páginas visitadas, mas necessita que um novo Crawler seja instanciado para cada site diferente.
Obs.: Fica a critério do desenvolvedor, de acordo com seu contexto, optar por um crawler independente por site ou fazer um atributo na classe referente ao site, generalizando suas especificações. Outra observação interessante é que esse crawler obtém apenas as páginas da página inicial e não continua o processo rastreando os links encontrados. Porém, é possível adaptar para que isso ocorra, assim como visto no capítulo anterior.
Rastreando vários tipos de página
Quando estamos interessados em rastrear todos os links internos de um site, muitos desafios podem aparecer no caminho, pois nunca sabemos o que será obtido ao navegarmos através desses links. Felizmente, existem maneiras de identificar o tipo da página:
Pelo URL: Todas as postagens de blog em um site podem conter um URL (http://example.com/blog/title-of-post, por exemplo)
Pela presença ou ausência de determinados campos em um site: Se uma página tiver uma data, mas não o nome do autor ele pode ser classificada como um comunicado de imprensa, por exemplo. Outro caso é se a página tiver título, uma imagem principal, e nenhum conteúdo principal, pode ser uma página de produto.
Pela presença de determinadas tags na página que a identifiquem: É possível tirar proveito das tags, mesmo que os dados da página não sejam coletados. Por exemplo, caso haja uma área de produtos relacionados, seu crawler pode buscar tags como "<\div id="produtos-relacionados">" para identificar essa como uma página de produto, mesmo que não seja o foco principal da sua aplicação.
Para não perder o controle sobre os vários tipos de páginas é necessário vários tipos de objeto em Python. Podemos fazer isso de duas maneiras:
Adicionar um atributo pageType no objeto de página web, caso todas as páginas/conteúdo possuírem conteúdos semelhantes:
Caso as páginas/conteúdo sejam muito diferentes entre si (contêm tipos diferentes de campos), podemos criar novos objetos para cada tipo de página. Apesar disso ainda teremos dados comuns para todas as páginas, uma situação ideal para o uso de herança:
Pensando nos modelos de web crawlers
Na internet, há muitas informações espalhadas é importante saber quais delas são realmente necessárias. Quando coletamos dados de várias fontes e domínios, sempre devemos normaliza-los. Lidar com dados comparáveis é muito mais simples do que aqueles que dependem do formato original.
Em muitos casos, precisamos desenvolver scrapers pensando na adição futura de outras fontes de dados. Mesmo que um site não pareça se enquadrar ao seu modelo à primeira vista, ser capaz de perceber padrões economiza tempo, dinheiro e possíveis contratempos a longo prazo. As conexões entre os dados também não devem ser ignoradas, entender como os atributos das informações que você deseja serão armazenados obtidos e conceituados é uma tarefa importante.
Arquitetura de software é um assunto amplo e importante que pode exigir muito tempo de experiencia para dominá-lo. Porém, felizmente, ao perceber os padrões que se repetem é possível adquirir habilidades mais rapidamente e facilmente quando falando da arquitetura do web scraping, exigindo apenas um cuidado maior no planejamento do seu projeto.
Last updated