DEV Community

Cover image for Ingestão de Dados com Web Scraping
Daniel Coutinho
Daniel Coutinho

Posted on

Ingestão de Dados com Web Scraping

Web scraping é uma técnica de extração de dados da web usando um programa ou script para automatizar o processo. É uma forma de coletar informações de sites de forma estruturada, acessando o código HTML das páginas e extraindo os dados desejados.

Essa ferramenta é valiosa no mundo da Engenharia de Dados, pois permite a obtenção e transformação de dados da web em formatos adequados para análise, integração em sistemas e aplicativos, pesquisa de mercado e monitoramento de informações relevantes.

Este projeto que decidi compartilhar hoje foi parte da minha experiência cursando o Bootcamp de Engenharia de Dados da How Bootcamps realizado com o auxílio dos facilitadores Rhuan Lima e Rafael Roberto Dias para aprender um pouco mais sobre essa poderosa ferramenta aliada de quem trabalha na área de dados.

Ilustração com fluxo de página web para web scraping para banco de dados

Objetivo do projeto

O objetivo desse primeiro projeto foi conseguir realizar a ingestão de dados a partir do site Viva Real para obter uma base com todos os imóveis à venda em Jacarepaguá utilizando apenas código em Python sem o uso de APIs.

Foi feita uma primeira camada de captura dessas informações através do Google Inspect utilizando a biblioteca Beautiful Soup e Requests modificando ao mínimo os dados. Posteriormente, a ideia é realizar uma segunda camada tratando esses dados com Pandas para análises.

O objetivo, que foi concluído com sucesso, foi de importar todas as informações do site para um arquivo .csv e .xlsx utilizando o código em um virtual environment criado para o projeto.

Um projeto simples, porém satisfatório de fazer por fornecer skills úteis e um banco de dados que pode ser utilizado para projetos futuros.

Código do projeto

As bibliotecas utilizadas no projeto, como citado anteriormente, foram Pandas, Beautiful Soup e Requests.

import requests
from bs4 import BeautifulSoup as bs
import pandas as pd
Enter fullscreen mode Exit fullscreen mode

Realizada a importação das bibliotecas, foi feita uma leitura da URL da região específica de onde os dados serão capturados com uma variável i que varia de acordo com a página acessada pelo script e feito um requestarmazenando o resultado em uma variável soup.

url = 'https://www.vivareal.com.br/venda/rj/rio-de-janeiro/zona-oeste/jacarepagua/?pagina={}'
i = 1
ret = requests.get(url.format(i))
soup = bs(ret.text)
Enter fullscreen mode Exit fullscreen mode

Para se certificar que houve uma captura completa dos dados, verifica-se o total de imóveis recebidos via requestutilizando soup.find na classe referente a essa informação.

qtd_imoveis = soup.find(
    'strong', {'class': 'results-summary__count js-total-records'})
# Removendo o ponto no número total de imóveis e transformando em float
qtd_imoveis = float(qtd_imoveis.text.replace('.', ''))
Enter fullscreen mode Exit fullscreen mode

Logo, é criado o data frame que receberá todas as informações.

df = pd.DataFrame(
    columns=[
        'descricao',
        'endereco',
        'area',
        'quartos',
        'wc',
        'vagas',
        'valor',
        'condominio',
        'wlink'
    ]
)
Enter fullscreen mode Exit fullscreen mode

Com o df criado, realiza-se um loop utilizando o total de imóveis comparando com o tamanho do df fazendo while qtd_imoveis > df.shape[0] e um segundo loop para para passar por todos os imóveis das páginas.

Para cada um dos itens pode dar um erro por falta de valores - por exemplo, imóveis que não tem valor de condomínio no card não vão retornar um valor para variável condomínio - e a forma de resolver isso é utilizando try e except para indicar o que fazer quando não é encontrado um valor desejável.

i = 0

while qtd_imoveis > df.shape[0]:
    print(f"Valor i: {i} \t\t qtd_imoveis: {df.shape[0]}")
    i = i+1
    ret = requests.get(url.format(i))
    soup = bs(ret.text, features="lxml")
    houses = soup.find_all(
        'a', {'class': 'property-card__content-link js-card-title'})

    for house in houses:  

        # Capturando os dados dos imóveis
        try:
            # Capturando a descrição no site
            descricao = house.find(
                'span', {'class': 'property-card__title js-cardLink js-card-title'}).text
            descricao = descricao.strip()  # Removendo os espaços
        except:
            descricao = None

        # Realizar o mesmo procedimento para os outros dados desejados
        try:
            endereco = house.find(
                'span', {'class': 'property-card__address'}).text.strip()
        except:
            endereco = None
        try:
            area = house.find(
                'span', {'class': 'js-property-card-detail-area'}).text.strip()
        except:
            area = None
        try:
            # Pegando apenas o span do texto para capturar apenas o número
            quartos = house.find(
                'li', {'class': 'js-property-detail-rooms'}).span.text.strip()
        except:
            quartos = None
        try:
            wc = house.find(
                'li', {'class': 'js-property-detail-bathroom'}).span.text.strip()
        except:
            wc = None
        try:
            vagas = house.find(
                'li', {'class': 'js-property-detail-garages'}).span.text.strip()
        except:
            vagas = None
        try:
            valor = house.find(
                'div', {'class': 'property-card__price'}).p.text.strip()
        except:
            valor = None
        try:
            condominio = house.find(
                'strong', {'class': 'js-condo-price'}).text.strip()
        except:
            condominio = None
        try:
            wlink = 'https://www.vivareal.com.br' + house['href']
        except:
            wlink = None

        df.loc[df.shape[0]] = [
            descricao,
            endereco,
            area,
            quartos,
            wc,
            vagas,
            valor,
            condominio,
            wlink
        ]
Enter fullscreen mode Exit fullscreen mode

Por fim, é gerado um arquivo .csv com o banco de dados armazenado na variável df para um arquivo imoveis_jacarepagua.csv.

df.to_csv('imoveis_jacarepagua.csv', sep=';', index=False)
Enter fullscreen mode Exit fullscreen mode

Resultado final:
Resultado final do dataframe com as colunas e linhas desejadas

Link do GitHub para o código: https://lnkd.in/dSemzQ52

Latest comments (0)