Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Web scraping dos dados de quantidades de disciplinas ofertadas #86

Closed
7 tasks done
Matheuspimentell opened this issue Mar 17, 2022 · 11 comments
Closed
7 tasks done

Comments

@Matheuspimentell
Copy link
Collaborator

Matheuspimentell commented Mar 17, 2022

Descrição

Realizar o scraping dos dados do SIGAA relacionados à quantidade de disciplinas ofertadas pelo departamento: FACULDADE DO GAMA - BRASÍLIA.

Tarefas

  • Contar quantas matérias disponíveis existem no departamento: FACULDADE DO GAMA - BRASÍLIA
  • Apresentar, no terminal, os nomes das matérias encontradas.
  • Apresentar. no terminal, a quantidade total de matérias no departamento.
  • Criação de um "tutorial" para o scraping realizado.

Critérios de aceitação

  • A quantidade de matérias contadas pelo algoritimo deve ser igual à quantidade de matérias contadas ao acessar o SIGAA.
  • Os nomes das matérias contadas devem ser mostrados em tempo de execução do algoritimo.
  • O "tutorial" deve ser postado em forma de comentário desta issue.
@gabrielm2q
Copy link
Collaborator

Iniciamos a busca de dados da listagem do SIGAA.
Até o momento, o código já é capaz de buscar, contar e imprimir todas as disciplinas disponíveis no departamento selecionado (FGA).

Abaixo, segue o código produzido até o momento.

import time
import requests
#import pandas as pd
#from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from webdriver_manager.firefox import GeckoDriverManager
#import json


url = "https://sig.unb.br/sigaa/public/turmas/listar.jsf?aba=p-ensino"

option = Options()
option.headless = True
driver = webdriver.Firefox(executable_path=GeckoDriverManager().install())

driver.get(url)
time.sleep(6)


#driver.find_element_by_xpath("//*[@id='formTurma:inputDepto']").click()
driver.find_element_by_id("formTurma:inputDepto").click()
driver.find_element_by_xpath('//*[@id="formTurma:inputDepto"]/option[79]').click()
driver.find_element_by_name('formTurma:j_id_jsp_1370969402_11').click()

 

contadorMaterias = 0
element = driver.find_elements_by_class_name('tituloDisciplina')
for k in element:
    html_content = k.get_attribute('innerHTML')
    print(html_content)
    contadorMaterias += 1

print('Total de disciplinas apresentadas na listagem: ', contadorMaterias)

# element1 = driver.find_elements_by_class_name('linhaPar')
# element2 = driver.find_elements_by_class_name('linhaImpar')
# for k in element1:
#     html_content = k.get_attribute('outerHTML')
#     #print(html_content)
#     i += 1
# for k in element2:
#     html_content = k.get_attribute('outerHTML')
#     #print(html_content)
#     i += 1

driver.quit()

Colaboradores

@AdneMoretti
@gabrielm2q

@AdneMoretti
Copy link
Collaborator

As partes comentadas do código acima podem ser utilizadas futuramente para acessar todas as turmas e calcular o total de turmas do departamento.

# element1 = driver.find_elements_by_class_name('linhaPar')
# element2 = driver.find_elements_by_class_name('linhaImpar')
# for k in element1:
#     html_content = k.get_attribute('outerHTML')
#     #print(html_content)
#     i += 1
# for k in element2:
#     html_content = k.get_attribute('outerHTML')
#     #print(html_content)
#     i += 1

@gabrielm2q
Copy link
Collaborator

Para complementar o código produzido, estaremos elaborando um pequeno "tutorial" para a execução do código, mostrando quais tecnologias foram utilizadas e como realizar a instalação.

@gabrielm2q
Copy link
Collaborator

Além disso, é possível evoluir o código com a estruturação dos dados recebidos, de modo a produzir um arquivo Json com todos os dados retirados do site, de modo a facilitar a inserção no BD.

@gabrielm2q
Copy link
Collaborator

O seguinte vídeo possui explicações que podem ajudar no entendimento do Web Scraping utilizando o Selenium, BeautifulSoup e o Pandas.
Vídeo: Python na Prática fazendo Web Scraping (de JavaScript dinâmico)

gabrielm2q added a commit that referenced this issue Mar 22, 2022
Co-authored-by: AdneMoretti morettiadne1@gmail.com
@oCaioOliveira
Copy link
Collaborator

oCaioOliveira commented Mar 24, 2022

from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from webdriver_manager.firefox import GeckoDriverManager


option = Options()
option.headless = True
driver = webdriver.Firefox(executable_path=GeckoDriverManager().install())


def acessarURL():
    url = "https://sig.unb.br/sigaa/public/turmas/listar.jsf?aba=p-ensino"
    driver.get(url)


def selecionarNivelEnsino():
    botaoCampoEnsino = driver.find_element_by_id('formTurma:inputNivel')
    botaoGraduacao = driver.find_element_by_xpath('//*[@id="formTurma:inputNivel"]/option[3]')
    botaoCampoEnsino.click()
    botaoGraduacao.click()


def selecionarUnidade():
    botaoUnidade = driver.find_element_by_id('formTurma:inputDepto')
    botaoFGA = driver.find_element_by_xpath('//*[@id="formTurma:inputDepto"]/option[79]')
    botaoUnidade.click()
    botaoFGA.click()


def acionarBotaoBuscar():
    botaoBuscar = driver.find_element_by_name('formTurma:j_id_jsp_1370969402_11')
    botaoBuscar.click()


def verificaVagas():
    contadorDocentes = 0
    contadorVagas = 0
    element1 = driver.find_elements_by_xpath("//td[@style='text-align: center;']")
    for x in element1:
        resto = contadorVagas % 2
        html_content = x.get_attribute('innerHTML')
        if resto == 1: 
            disciplina = driver.find_elements_by_xpath("//td[@class='nome']")[contadorDocentes]
            turma = disciplina.get_attribute('innerHTML')
            print(f'Vagas em {turma}: {html_content}')
            contadorDocentes += 1
        contadorVagas += 1
    return contadorVagas


def fecharJanela():
    driver.quit()


def main():
    acessarURL()
    driver.implicitly_wait(6)
    selecionarNivelEnsino()
    selecionarUnidade()
    acionarBotaoBuscar()
    contadorVagas = verificaVagas()
    print(f'Numero de Turmas encontradas: {contadorVagas/2}')
    fecharJanela()


main()

Código formatado de uma forma diferente, porém com as mesmas lógicas e funcionalidades, diferença para auxiliar na leitura para quem não pode participar do desenvolvimento (funcionalidades separadas em funções e variáveis melhor descritas).

@gabrielm2q
Copy link
Collaborator

Versionamento

Na produção da primeira versão do código, foram usados os seguintes softwares:

  • urllib3 (versão 1.21.1)
  • webdriver-manager (versão 3.5.3)
  • selenium (versão 4.1.0)
  • Navegador Mozilla (versão 98.0.2)

Configuração de Ambiente

Para a execução do projeto, é necessário instalar o Selenium. Para tal, utilize o seguinte comando no terminal (Ubuntu/Linux):

pip3 install selenium==4.1.0

Instale o webdriver manager:

pip3 install webdriver-manager==3.5.3

Para instalar o urllib3 na versão correta talvez seja necessário desinstalar a versão já existente. Para isso, use o comando no terminal:

pip3 uninstall urllib3

Então, instale o urllib3 com o seguinte comando:

pip3 install urllib3==1.21.1

Por fim, para verificar se as versões dos softwares instalados estão corretas, basta usar o seguinte comando e verificar a versão de cada um deles:

pip3 list

Código comentado

# Importando as bibliotecas e módulos necessários para a execução do scraping
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.firefox.options import Options
from webdriver_manager.firefox import GeckoDriverManager

# Armazenando a URL da página inicial da listagem do SIGAA
url = "https://sig.unb.br/sigaa/public/turmas/listar.jsf?aba=p-ensino"

# Configurando o driver do navegador e passando a URL do SIGAA para ele
option = Options()
option.headless = True
servicoFirefox = Service(GeckoDriverManager().install())
driver = webdriver.Firefox(service=servicoFirefox, options=option)
driver.get(url)

# Aqui temos uma pausa de 2 segundos para que o navegador carregue as
# informações necessárias antes de iniciar o scraping
time.sleep(2)

# Aqui estamos selecionando a opção "Graduação"
driver.find_element(By.ID, "formTurma:inputNivel").click()
driver.find_element(By.XPATH, '//*[@id="formTurma:inputNivel"]/option[3]').click()

# Aqui estamos selecionando o departamento "Faculdade do Gama"
driver.find_element(By.ID, "formTurma:inputDepto").click()
driver.find_element(By.XPATH, '//*[@id="formTurma:inputDepto"]/option[79]').click()

# Clicando no botão de busca
driver.find_element(By.NAME, 'formTurma:j_id_jsp_1370969402_11').click()

# Aqui temos uma pausa de 2 segundos para que o navegador carregue as
# informações necessárias antes de iniciar o scraping
time.sleep(2)

# contadorMaterias armazenará a quantidade de matérias contadas na lista
contadorMaterias = 0

# Aqui estamos importando uma lista com todos os títulos de matérias
# presentes na página do SIGAA
element = driver.find_elements(By.CLASS_NAME, 'tituloDisciplina')

# Vamos passar por todos os elementos (matérias) da lista de oferta
# para printar todas elas e contar a quantidade total de matérias
for k in element:
    html_content = k.get_attribute('innerHTML')
    print(html_content)
    contadorMaterias += 1

print('Quantidade de matérias apresentadas na listagem: ', contadorMaterias)

# Encerrando o navegador
driver.quit()

Tutorial produzido por:
@AdneMoretti
@gabrielm2q

@gabrielm2q
Copy link
Collaborator

O código foi refatorado de forma a retirar quaisquer funcionalidades obsoletas (ou deprecated) e de modo a proporcionar uma melhor visualização do mesmo, comentando e separando as funcionalidades. Segue para revisão.

gabrielm2q added a commit that referenced this issue Mar 28, 2022
Co-authored-by: oCaioOliveira <ocaio.ooliveira@gmail.com>
@gabrielm2q
Copy link
Collaborator

Seguindo o exemplo deixado pelo @oCaioOliveira, o código foi "refatorado" de modo a dividir todas as atividades em métodos e centralizar os passos da execução do código na "main()".
Novamente, o código segue para revisão.

@oCaioOliveira
Copy link
Collaborator

Revisão

O código foi revisado e está coletando os dados normalmente, mas não está inicializando o firefox, para inicializá-lo basta retirar as linhas 13 e 14 e inserir o seguinte comando:

driver = webdriver.Firefox(executable_path=GeckoDriverManager().install())

@gabrielm2q
Copy link
Collaborator

gabrielm2q commented Mar 28, 2022

Feedback da Revisão

O Firefox é iniciado no background devido ao parâmetro "options=option" passado para o driver do mesmo. Para exibir o navegador, basta retirar este parâmetro! Todavia, com ou sem a exibição do navegador, os dados são coletados e disponibilizados normalmente, conforme citado.

Abaixo, o trecho do código (linha 14) responsável por exibir ou ocultar o navegador:

driver = webdriver.Firefox(service=servicoFirefox, options=option)

Como foi passado que os dados estão sendo coletados normalmente, a issue será fechada.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants