Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
robertopucp
GitHub Repository: robertopucp/1eco35_2022_2
Path: blob/main/Trabajo_final/grupo1/Grupo1_Pregunta2_Web_Scraping.ipynb
2714 views
Kernel: Python 3 (ipykernel)

Pregunta 2: Web Scraping

# Instalo estas nuevas librerías que me servirán más adelante (como explicaré) #pip install html5lib #pip install dataframe-image # Librerías usadas: # Selenium es la librería que nos servirá para usar el método de web scraping # html5lib es para los archivos en excel descargados que no se puede leer con la herramienta tradicional de read_excel # Pandas para poder manipular DataFrames # dataframe_image nos servirá para descargar el DataFrame como imagen import html5lib from selenium import webdriver # Nos permite navegar en la web import re import datetime import time import unidecode import pandas as pd from bs4 import BeautifulSoup import requests from requests import get from selenium.webdriver.support.ui import Select from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.common.exceptions import NoSuchElementException from tqdm import tqdm from selenium.webdriver.common.action_chains import ActionChains import os import numpy as np import pandas as pd from pandas import Series, DataFrame import dataframe_image as dfi # Indico el directorio: user = os.getlogin() os.chdir(f"C:/Users/{user}/Documents/GitHub/1ECO35_2022_2/Lab11") #Ubicamos el chromedriver y la página web de donde vamos a scrapear path_driver = r"chromedriver.exe" driver = webdriver.Chrome(path_driver) driver.get("http://www2.juntos.gob.pe/infojuntos/") #Insertar los años a consultar lista_años = ['2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021']
C:\Users\Alfonso\AppData\Local\Temp\ipykernel_14564\2948869864.py:45: DeprecationWarning: executable_path has been deprecated, please pass in a Service object driver = webdriver.Chrome(path_driver)
# Iteramos para cada elemento de la lista, de modo que ingrese la fecha a consultar en la # página web. for i in lista_años: # Hago que descanse por 1 segundo el código para que cargue completamente la página. time.sleep(1) # Primero, creo el botón que corresponda al Vraem # A este, lo llamo buttom_Vraem, el cual va a estar identificado según el xpath de Vraem. # Para ello, empleo: driver.find_element (By.XPATH, "la ruta en xpath") buttom_Vraem = driver.find_element (By.XPATH, '/html/body/div[1]/aside/section/ul/li[1]/ul/li[2]/a') # Ahora, con .click() hago que dé click sobre el botón de Vraem. buttom_Vraem.click() # Debo seleccionar los años del dropdown menu: # Usaré la herramienta Select( ) y adentro ubicaré al menú con xpath. year_buttom = Select( driver.find_element (By.XPATH,'//*[@id="canho"]') ) # Como va a iterar dentro de los valores de la lista, en cada pasada, va a # ir colocándose cada año dentro del menú con la herramienta .select_by_value() year_buttom.select_by_value(i) # Hago que descanse por 3 segundos para que cargue completamente la página. time.sleep(3) # Una vez en el año que corresponda, descargaré el excel indicado. # Para ello, en este caso, a pesar de que también es un dropdown menu, la resolución debe ser distinta, # pues el botón para la descarga está dentro de otro. # Primero, hago que dé click dentro del ícono de excel: # Para ello, primero, ubico el xpath del ícono de excel. # A esta variable que identifica el botón lo llamo excel_buttom. excel_buttom = driver.find_element (By.XPATH,'/html/body/div[1]/div/section[2]/div[2]/section[2]/div[1]/div[1]/div/div') # Luego, hago que dé click. excel_buttom.click() # Hago que descanse por 3 segundos para que cargue completamente la página. time.sleep(3) # Ahora, voy al siguiente nivel y también ubico su xpath. Y lo sobreescribo sobre excel_buttom. excel_buttom = excel_buttom.find_element (By.XPATH, '/html/body/div[1]/div/section[2]/div[2]/section[2]/div[1]/div[1]/div/div/ul') # Este será el último objeto. Ubico su xpath. También, lo sobreescribo sobre excel_buttom. excel_buttom = excel_buttom.find_element (By.XPATH, '//*[@id="bimexp"]') # Ahora, hago que dé click, de manera que se decarga el excel. excel_buttom.click()
# Ahora, importamos las bases descargadas con .read_html() vraem_2014 = pd.read_html(r'../../../../Downloads/Detalle.xls') vraem_2015 = pd.read_html(r'../../../../Downloads/Detalle (1).xls') vraem_2016 = pd.read_html(r'../../../../Downloads/Detalle (2).xls') vraem_2017 = pd.read_html(r'../../../../Downloads/Detalle (3).xls') vraem_2018 = pd.read_html(r'../../../../Downloads/Detalle (4).xls') vraem_2019 = pd.read_html(r'../../../../Downloads/Detalle (5).xls') vraem_2020 = pd.read_html(r'../../../../Downloads/Detalle (6).xls') vraem_2021 = pd.read_html(r'../../../../Downloads/Detalle (7).xls') # Creo un DataFrame vacío sobre el que se hará el append al final df = pd.DataFrame() # Creamos una lista con los DataFrames: lista_excel = [vraem_2014, vraem_2015, vraem_2016, vraem_2017, vraem_2018, vraem_2019, vraem_2020, vraem_2021]
# Iteramos sobre los archivos descargados e importados para hacer la limpieza y aplicar un append. for i in lista_excel: # Convertimos el archivo que está en lista a un DataFrame con [0] i = i[0] # Ahora, hacemos la limpieza: # Primero, eliminaremos algunas filas y columnas, para lo cual aplicaremos .drop() # Para eliminar las columnas correspondientes a los bimestres y solo quedarme con la correspondiente a Anual: # debo indicar qué columnas son a las que me refiero; eso lo hago con .columns[[1,2,3,4,5,6]] # Aplico axis = 1 para indicarle que me refiero a la columna (y no a fila). i = i.drop(i.columns[[1,2,3,4,5,6]],axis = 1) # Ahora, eliminaremos las filas innecesarias: # Para ello, dentro de .drop() coloco [0, 1, 2, 14] # Así, le indico qué filas quiero eliminar según el índice. # La primera fila (de índice 0) contiene el título; # la segunda (de índice 1), el nombre de reporte; # y la tercera (de índice 2), el encabezado de bimestre o anual # La fila de índice 14 es aquella que señalan la Fuente y el Reporte. i = i.drop([0, 1, 2, 14]) # Transponemos el DataFrame: i = i.transpose() # Hago que la primera fila (de índice 0) pase a ser el nombre de las columnas y luego elimino esta fila: # Primero, aplico .rename() para renombrar las columnas o variables del DataFrame # Luego, indico que seleccionaré la primera fila con .iloc[0] # Con .loc[1:] le indico que me muestre el DataFrame desde la observación 1 (que es la segunda fila), # de modo que la observación con índice 0 (que pasó a ser el nombre de las columnas) queda removida. # Finalmente, aplico reset_index para que el índice de las filas quede reseteado. # Con drop = True hago no se genere una columna adicional con la serie de índice original y que se elimine. i = i.rename(columns=i.iloc[0]).loc[1:].reset_index(drop = True) # Elimino las columnas "Establecimientos de Salud" e "Instituciones Educativas" # Empleo el mismo método anterior; pero aquí uso labels y con axis= 1 le indico que opero sobre columnas. i = i.drop(["Establecimientos de Salud", "Instituciones Educativas"], axis = 1) # Finalmente, apilo esta observación sobre el DataFrame creado antes. df = df.append(i)
C:\Users\Alfonso\AppData\Local\Temp\ipykernel_14564\4094679443.py:43: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead. df = df.append(i) C:\Users\Alfonso\AppData\Local\Temp\ipykernel_14564\4094679443.py:43: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead. df = df.append(i) C:\Users\Alfonso\AppData\Local\Temp\ipykernel_14564\4094679443.py:43: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead. df = df.append(i) C:\Users\Alfonso\AppData\Local\Temp\ipykernel_14564\4094679443.py:43: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead. df = df.append(i) C:\Users\Alfonso\AppData\Local\Temp\ipykernel_14564\4094679443.py:43: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead. df = df.append(i) C:\Users\Alfonso\AppData\Local\Temp\ipykernel_14564\4094679443.py:43: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead. df = df.append(i) C:\Users\Alfonso\AppData\Local\Temp\ipykernel_14564\4094679443.py:43: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead. df = df.append(i) C:\Users\Alfonso\AppData\Local\Temp\ipykernel_14564\4094679443.py:43: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead. df = df.append(i)
# Este es el dataframe con cada observación apilada (aún falta agregar la columna con los años) df
# Creo una variable adicional con el nombre year, cuyos valores serán los de la lista de años (lista_años) entre 2014 y 2021: df ['year'] = lista_años
# Aplico reset_index para que el índice de las filas quede reseteado. # Con drop = True y inplace = True hago que, respectivamente, no se genere una columna adicional # con la serie de índice original y que se sobreescriban automáticamente los cambios en el mismo DataFrame. df.reset_index(drop = True, inplace=True) # Creo una variable adicional llamada Imagen2, como se pone en la lista de ejercicios: Imagen2 = df #Exporto el DataFrame como imagen con dfi.export() dfi.export(Imagen2,r"../../../../Downloads/ws_juntos.png", dpi=300)
# Observamos cómo queda el Dataframe requerido Imagen2