#!/usr/bin/env python
# coding: utf-8

# # INTRODUCCIÓN AL WEBSCRAPPING CON PYTHON

# In[1]:


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime

import warnings
warnings.filterwarnings('ignore')

pd.options.display.float_format = '{:.2f}'.format #Desactivar notación científica en pandas:
np.set_printoptions(suppress=True) #Desactivar notación científica en numpy:
pd.set_option('display.max_columns', None) #comando para mostrar todas las columnas


# In[4]:


# conda install -c conda-forge scrapy


# Nos conectaremos a la web reddit y descargaremos información de alguno de los foros existentes.
# 
# Esta primera parte la ejecutaremos en la consola del ordenador.  Los comandos a ejecutar
# - Abrir un terminal
# - Escribir: scrapy shell
# - Una vez en la shell, escribir: fetch("https://www.reddit.com/r/gameofthrones/")
# - Cuando termine, escribir: view(response)
# 
# 
# ### Objetivos del scrapeo:
# - Extraer el título de cada post.
# - Extraer el total de votos de cada post.
# - Extraer el número total de comentarios.
# - Fecha de creación del post

# Extracción del titulo:  
# response.css(".title::text").extract()

# In[ ]:





# # Scrapeo información liga (página estática).
# ### Pasos ya vistos en una sesión previa

# In[10]:


import requests
import pandas as pd


# In[13]:


urls = ["http://www.marca.com/estadisticas/futbol/primera/2016_17/jornada_38/",
         "http://www.marca.com/estadisticas/futbol/primera/2017_18/jornada_38/",
         "http://www.marca.com/estadisticas/futbol/primera/2018_19/jornada_38/",
         "http://www.marca.com/estadisticas/futbol/primera/2019_20/jornada_38/",
         "http://www.marca.com/estadisticas/futbol/primera/2020_21/jornada_38/"]


# In[14]:


tablas = []
for a in range(len(urls)):
    print(a)
    html = requests.get(urls[a]).content
    df_list = pd.read_html(html)
    tablas.append(df_list[-1]) # Nos quedamos con la ultima tabla descargada


# In[15]:


tablas[2]


# In[17]:


# La mayor parte de las páginas web actuales no son estáticas.  Son dinámicas y generan su contenido 'bajo demanda'.
# Por ello, este método no sirve en ellas.


# In[18]:


# Probemos lo siguiente
url = "https://www.marca.com/futbol/primera-division/clasificacion-historica.html"


# In[19]:


html = requests.get(url).content
df_list = pd.read_html(html)
df = df_list[-1] # Nos quedamos con la ultima tabla descargada


# In[20]:


df


# In[21]:


# Y ahora ésto...
url = "https://www.marca.com/futbol/primera-division/clasificacion.html"
html = requests.get(url).content
df_list = pd.read_html(html)
df = df_list[-1]


# Ésta última url se genera de manera dinámica, frente a la de resultados históricos que es estática. Necesitamos otro método para acceder a ese contenido.

# ### Parseo HTML con BeautifulSoup
# A través de BeautifulSoup, podemos parsear HTML a XML.  Ésto nos permite navegar a través del XML como si lo hiciéramos a través de la estructura DOM de la página.
# Para navegar, buscaremos los elementos del XML a través de sus nombres, clases, ID's o relaciones con otros elementos (padre - hijo).
# 
# Nos permite scrapear sólo web estáticas.

# In[25]:


get_ipython().system('pip install beautifulsoup4')


# In[2]:


from bs4 import BeautifulSoup
import requests


# In[3]:


url = 'https://www.allsides.com/media-bias/media-bias-ratings'
r = requests.get(url)
print(r.content[:100])


# In[4]:


soup = BeautifulSoup(r.content, 'html.parser')


# In[5]:


# Para extraer un elemento cuya CLASE sea temp <a class="temp"></a>
soup.select_one('.temp')


# In[6]:


# Para extraer un elemento cuyo ID sea temp <a id="temp"></a>
soup.select_one('#temp')
# Siempre que podamos, intentar acceder a los elementos de la página a través de un ID


# In[7]:


#Para extraer un elemento cuyas clases seas "temp" y "example" <a class="temp example"></a>
soup.select_one('.temp.example')


# In[8]:


#Para extraer un elemento anidado a otro, por ejemplo elemento 'a' anidado con la clase temp <div class="temp"><a></a></div>
soup.select_one('.temp a')


# In[9]:


# Para extraer una etiqueta como <body></body> usaremos
soup.select_one('body')

# Para extraer una etiqueta como <a></a> usaremos soup.select_one('a')
# Buscar la etiqueta body en el código de la página y comprobar que contiene el contenido de la tabla en tbody


# In[10]:


# Extraemos el objeto tbody que está en clase (table body)
soup.select_one('tbody')


# In[11]:


soup.select('tbody')


# In[12]:


# en cada un de los tr de tbody están las líneas de la tabla
rows = soup.select('tbody tr')


# In[13]:


rows


# ### Extracción de los elementos de la tabla

# In[14]:


# La primera celda de la tabla que queremos extraer está bajo la clase 'views-field views-field-title source-title'
row = rows[0]
medio = row.select_one('.source-title')
medio2 = row.select_one('.source-title').text.strip()
print(medio,"\n")
print(medio2)

# También habríamos podido seleccionar el texto así: texto = row.select_one('.views-field.views-field-title.source-title')


# In[15]:


row


# In[16]:


row.select_one('.views-field').text.strip()


# In[17]:


# En este objeto y href, tenemos la ruta relativa (la url parcial) para acceder al recurso (la página donde se aloja).
ruta_relativa = row.select_one('.source-title a')['href']
print(row.select_one('.source-title'))
print(ruta_relativa)


# In[18]:


# El siguiente elemento de la tabla es una imagen.  Extraemos el dato que está contenido en la url.  Cada url carga una imagen distinta.
imagen = row.select_one('.views-field-field-bias-image a')['href']
print(imagen)
imagen = imagen.split('/')[-1]
print(imagen)


# In[95]:


# Ya tenemos el dato.


# In[19]:


# Extraemos ahora el feedback por fila
acuerdo = row.select_one('.agree').text
acuerdo = int(acuerdo)

desacuerdo = row.select_one('.disagree').text
desacuerdo = int(desacuerdo)

ratio_acuerdo = acuerdo / desacuerdo

print(f"Acuerdo: {acuerdo}, Desacuerdo: {desacuerdo}, Ratio {ratio_acuerdo:.3f}")


# In[20]:


# Nos falta un elemento por extraer, el texto a la derecha en Community feedback
print(row.select_one('.community-feedback-rating-page'))


# In[103]:


#¿Qué está pasando? Mirar -> div class="community-feedback-rating-page" > == $0
# El dato se genera al vuelo mediante js
# requests no puede lidiar con este tipo de dato.


# In[21]:


# Creamos la tabla registro a registro
tabla= []

for row in rows:
    d = dict()
    
    d['medio'] = row.select_one('.source-title').text.strip()
    d['url'] = 'https://www.allsides.com' + row.select_one('.source-title a')['href']
    d['imagen'] = row.select_one('.views-field-field-bias-image a')['href'].split('/')[-1]
    d['acuerdo'] = int(row.select_one('.agree').text)
    d['desacuerdo'] = int(row.select_one('.disagree').text)
    d['ratio_acuerdo'] = d['acuerdo'] / d['desacuerdo']
    
    tabla.append(d)


# In[22]:


tabla = pd.DataFrame(tabla)
tabla.head()


# In[23]:


tabla


# Problema, sólo hemos extraído la primera página, pero hay más.  No podemos extraer el resto con BeautifulSoup, puesto que se generan mediante código js

# Para acceder a páginas que crean su contenido dinámicamente, tenemos que utilizar Selenium.  Selenium es una herramienta open source que sirve para testear el funcionamiento de las páginas web, pero se usa principalmente para Webscrapping.
