Web Scraping e SQLite

Author: Uallas Leles
Date: 23 de junho, 2021



Obtendo dados de páginas web e salvando em um banco de dados:

O objetivo deste projeto é obter dados de páginas web através de web scraping e salvá-los em um banco de dados SQLite.
Neste trabalho, especificamente, não há preocupação na relevância dos dados ou na exploração de insights. A finalidade é construir um workflow básico que faça a extração e estruturação dos dados para etapas seguintes.


Definição do Problema:
Vamos obter dados de listas de repositórios no GitHub através de web scraping, e então salvá-los em um banco de dados.



Mão na Massa

Importação dos Pacotes

import requests
from lxml import html
import pandas as pd
import sqlite3

Obtendo os Dados

# VARIÁVEIS
OVERWRITE = False

# Caso deseje acumular ou não as listas de reposiórios de diferentes usuários
# URL's
URL_LIST = []
URL_LIST.append('https://github.com/uallasleles?tab=repositories')
URL_LIST.append('https://github.com/vitorfs?tab=repositories')
URL_LIST.append('https://github.com/franklin390?tab=repositories')
URL_LIST.append('https://github.com/VictorSRocha?tab=repositories')

# Aqui colocamos a url da aba repositórios da página de cada usuário desejado
# Esta é a função que realiza a extração dos dados da página web.
def scraping_page(html):
    global user_repositories_list
    
    # Obtem um fragmento do html
    e = html.get_element_by_id("user-repositories-list")
    
    # Extraio os elementos
    for i in e.getchildren()[0]:
        for v in i.getchildren()[0:3]:

            try: repo_user = URL
            except: repo_user = ''

            try: repo_name = v.getchildren()[0].getchildren()[0].text_content().strip().replace('\n', '')
            except: repo_name = ''

            if len(repo_name) != 0:
                try: repo_fork = v.getchildren()[0].getchildren()[1].text_content().strip().replace('\n', '')
                except: repo_fork = ''

                try: repo_desc = v.getchildren()[1].getchildren()[0].text_content().strip().replace('\n', '')
                except: repo_desc = ''

                user_repositories_list = user_repositories_list.append(
                    {
                        'user': repo_user,
                        'name': repo_name,
                        'fork': repo_fork,
                        'desc': repo_desc
                    },
                    ignore_index = True)
                
    return user_repositories_list
# Dicionário para receber os dados
user_repositories_list = pd.DataFrame(columns=['user', 'name', 'fork', 'desc'])

# Neste loop executamos o scraping para cada url da lista e acumulamos os resultados em um dataframe.
for URL in URL_LIST:
    
    r = requests.get(URL)
    assert r.status_code == 200, f"Falha no request."

    # Retorna document_fromstring ou fragment_fromstring, com base em se a string parece um documento completo ou apenas um fragmento.
    HTML = html.fromstring(r.text)
    
    # Chama a função para o scraping
    user_repositories_list = scraping_page(HTML)
# Conferindo os dados
user_repositories_list.head(10)
user name fork desc
0 https://github.com/uallasleles?tab=repositories proj_20210623-Scraping_SQLite Fazendo scraping e salvando os dados em um ban...
1 https://github.com/uallasleles?tab=repositories uallasleles.github.io
2 https://github.com/uallasleles?tab=repositories proj_20210619-Early_Stage_Diabetes_Risk_Predic...
3 https://github.com/uallasleles?tab=repositories portfolio Relação de projetos, ideias e habilidades dese...
4 https://github.com/uallasleles?tab=repositories odoo Forked from odoo/odoo Odoo. Open Source Apps To Grow Your Business.
5 https://github.com/uallasleles?tab=repositories maintainer-tools Forked from OCA/maintainer-tools Odoo Maintainers Tools & conventions for OCA m...
6 https://github.com/uallasleles?tab=repositories unimed_bi Forked from dudanogueira/unimed_bi Sistema de Business Intelligence e Data Analyt...
7 https://github.com/uallasleles?tab=repositories orun Forked from katrid/orun Orun. Build Your Own Custom Python ERP/CRM Sof...
8 https://github.com/uallasleles?tab=repositories Odoo-14-Development-Cookbook-Fourth-Edition Forked from PacktPublishing/Odoo-14-Developmen... Odoo 14 Development Cookbook - Fourth Edition,...
9 https://github.com/uallasleles?tab=repositories Odoo-12-Development-Essentials-Fourth-Edition Forked from PacktPublishing/Odoo-12-Developmen... Odoo 12 Development Essentials, Fourth Edition...

Armazenando em um Banco de Dados

Para salvar o resultado temos que criar uma conexão com o banco de dados, criar uma tabela com os campos necessários e realizar o insert para cada registro do dataframe.

# Criando um banco e uma conexão.
con = sqlite3.connect('proj_20210623.db')
# Criando um cursor para acessar os dados.
cur = con.cursor()
# Definindo as instruções sql necessárias
sql_delete_table = '''DELETE FROM user_repositories_list'''
sql_create_table = '''CREATE TABLE IF NOT EXISTS user_repositories_list (user text, name text, fork text, desc text)'''
sql_insert_table = '''INSERT INTO user_repositories_list (user, name, fork, desc) VALUES (?, ?, ?, ?)'''
sql_query = '''SELECT * FROM user_repositories_list'''
# Criando a tabela
try:
    cur.execute(sql_create_table)
finally:
    if OVERWRITE:
        cur.execute(sql_delete_table)
# Inserindo os dados
for r in user_repositories_list.itertuples():
    cur.execute(sql_insert_table, r[1:])
con.commit()
pd.read_sql_query(sql_query, con)
user name fork desc
0 https://github.com/uallasleles?tab=repositories uallasleles.github.io SEM DESCRIÇÃO
1 https://github.com/uallasleles?tab=repositories proj_20210619-Early_Stage_Diabetes_Risk_Predic... SEM DESCRIÇÃO
2 https://github.com/uallasleles?tab=repositories portfolio Relação de projetos, ideias e habilidades dese...
3 https://github.com/uallasleles?tab=repositories odoo Forked from odoo/odoo Odoo. Open Source Apps To Grow Your Business.
4 https://github.com/uallasleles?tab=repositories maintainer-tools Forked from OCA/maintainer-tools Odoo Maintainers Tools & conventions for OCA m...
... ... ... ... ...
317 https://github.com/franklin390?tab=repositories Project_02_Group_Bimbo_Inventory_Demand Neste projeto de aprendizado de máquina, vamos...
318 https://github.com/VictorSRocha?tab=repositories VictorSRocha.github.io Website Profile
319 https://github.com/VictorSRocha?tab=repositories Prevendo-o-Nivel-de-Satisfacao-dos-Clientes
320 https://github.com/VictorSRocha?tab=repositories Prevendo-Demanda-de-Estoque-com-Base-em-Vendas Projeto para criação de um modelo para Previsã...
321 https://github.com/VictorSRocha?tab=repositories Deteccao-de-Fraudes-no-Trafego-de-Cliques-em-P... Projeto para criação de um algoritmo para Dete...

322 rows × 4 columns

# Não vou precisar modificar estes dados, mas caso queira saber, isso seria possível da seguinte forma:
sql_udt_desc = '''UPDATE user_repositories_list SET desc = "SEM DESCRIÇÃO" WHERE desc = ""'''
cur.execute(sql_udt_desc)
con.commit()
con.close()

Conclusão

Criei uma sequencia de código para extrair dados de uma página web, então salvei estes dados em um banco de dados SQLite chamado ‘proj_20210623.db’. A única parte que exige um pouco mais de trabalho é a construção da lógica do scraping, pois você terá que analisar a estrutura do documento html, identificar tags e definir uma estratégia para extrair o conteúdo desejado. Após a execução do processo, podemos recuperar estes dados para análise, ou então, dar sequencia utilizando linguagem SQL para gerar consultas, gerarmos relatórios, procedimentos, agregação com outros conjuntos de dados, transferí-los para outras pessoas, etc.

Fim