Scraping con Python, Liga BBVA de ESPN [Parte 1]

in #spanish8 years ago

Les cuento que ya termine de dar los últimos retoques a nuestro primer scraping en python sobre la Pagina de ESPN.


Les quiero aclarar que hay muchas formas de hacer las cosas y yo quiero hacerlas a mi manera tal vez no sea la mejor pero es la que creo mas sencilla de explicar.


Como introdución a esta entrada les diré como pienso hacer las entradas de Scraping en este Blog.
Primero voy a hacer la recolección de datos,  vamos a hablar un poco del código que usamos algunas veces vamos a hablar de mejoras del código.


Luego vamos a generar la salida lo mas parecida a la pagina(todo esto en la 1era entrada de cada Scrap).


En segundo lugar vamos a diseñar y generar la base de datos, en primera instancia con SQLITE.

Tercero vamos a hacer estudios comparativos de la Base de Datos vamos a generar Gráficas y Búsquedas.


A cuales paginas les voy a hacer Scraping?????' 


Yo creo que para empezar a la tabla de posiciones de Futbol Soccer, luego con la tabla de jugadores de cada equipo, ya con esto podemos generar otras tablas por filtración de las 2 primeras, Gráficos que no salen en otros sitios aquí los haremos.Al grano vamos a hacerle SCRAPING a esta pagina: ttp://www.espn.com.ve/futbol/posicionesenvivo/_/liga/esp.1/primera-division-de-espana


Para generar Gráficos interesantes, les vamos a hacer Scraping todos cada cierto tiempo esta Pagina y vamos a ir viendo unas gráficas interesantes.


 Así se ve la tabla:

Esta es la tabla de donde vamos a sacar la información, y este nuestro primer código:

import urllib2
from bs4 import BeautifulSoup
import re

# url that we are scraping
url = "http://www.espn.com.ve/futbol/posicionesenvivo/_/liga/esp.1/primera-division-de-espana"

page = urllib2.urlopen(url)

soup = BeautifulSoup(page, "lxml")


table = soup.find('table')

rows = table.find_all('tr')
results = []
for row in rows:
        table_headers = row.find_all('th')
        if table_headers:
            results.append([headers.get_text() for headers in table_headers])

        table_data = row.find_all('td')
        if table_data:
	    results.append([data.get_text() for data in table_data])


print results


El código es un poco enredado:


Primero nos conectamos con urllib2 con BeautifulSoup hacemos una sopa  "soup=BeautifulSoup(page, "lxml")".


Luego buscamos la etiqueta table "table = soup.find('table')"


Luego buscamos todas las filas "rows=table.find_all('tr')" y creamos la lista en blanco "results = []" 


Creamos un  bucle para recorrer las filas guardadas en rows, ya en  el bucle buscamos las Cabeceras de las tablas o "th" y si existen les extraemos el texto.


Hacemos lo mismo con la data de las tablas o "td" y la extraemos con "get_text" al final imprimimos el resultado que es este:

[[u'30 de agosto de 2016Primera Divisi\xf3n de Espa\xf1a 2016/2017 Tabla de posiciones'], [u'\xa0', u'\xa0', u'\xa0', u'General', u'', u'Local', u'', u'Visitante'], [u'Pos.', u'', u'EQUIPO', u'Pts.', u'', u'PJ', u'G', u'E', u'P', u'GF', u'GC', u'Dif.', u'', u'G', u'E', u'P', u'GF', u'GC', u'', u'G', u'E', u'P', u'GF', u'GC'], [u'1', u'\n', u'Las Palmas', u'6', u'', u'2', u'2', u'0', u'0', u'9', u'3', u'6', u'', u'1', u'0', u'0', u'5', u'1', u'', u'1', u'0', u'0', u'4', u'2'], [u'2', u'\n', u'Barcelona', u'6', u'', u'2', u'2', u'0', u'0', u'7', u'2', u'5', u'', u'1', u'0', u'0', u'6', u'2', u'', u'1', u'0', u'0', u'1', u'0'], [u'3', u'\n', u'Real Madrid', u'6', u'', u'2', u'2', u'0', u'0', u'5', u'1', u'4', u'', u'1', u'0', u'0', u'2', u'1', u'', u'1', u'0', u'0', u'3', u'0'], [u'4', u'\n', u'Sevilla FC', u'4', u'', u'2', u'1', u'1', u'0', u'6', u'4', u'2', u'', u'1', u'0', u'0', u'6', u'4', u'', u'0', u'1', u'0', u'0', u'0'], [u'5', u'\n', u'Sporting Gij\xf3n', u'4', u'', u'2', u'1', u'1', u'0', u'2', u'1', u'1', u'', u'1', u'0', u'0', u'2', u'1', u'', u'0', u'1', u'0', u'0', u'0'], [u'6', u'\n', u'Deportivo La Coru\xf1a', u'4', u'', u'2', u'1', u'1', u'0', u'2', u'1', u'1', u'', u'1', u'0', u'0', u'2', u'1', u'', u'0', u'1', u'0', u'0', u'0'], [u'7', u'\n', u'Leganes', u'4', u'', u'2', u'1', u'1', u'0', u'1', u'0', u'1', u'', u'0', u'1', u'0', u'0', u'0', u'', u'1', u'0', u'0', u'1', u'0'], [u'8', u'\n', u'Eibar', u'3', u'', u'2', u'1', u'0', u'1', u'2', u'2', u'0', u'', u'1', u'0', u'0', u'1', u'0', u'', u'0', u'0', u'1', u'1', u'2'], [u'9', u'\n', u'Real Sociedad', u'3', u'', u'2', u'1', u'0', u'1', u'2', u'3', u'-1', u'', u'0', u'0', u'1', u'0', u'3', u'', u'1', u'0', u'0', u'2', u'0'], [u'10', u'\n', u'M\xe1laga', u'2', u'', u'2', u'0', u'2', u'0', u'3', u'3', u'0', u'', u'0', u'1', u'0', u'1', u'1', u'', u'0', u'1', u'0', u'2', u'2'], [u'11', u'\n', u'Atletico Madrid', u'2', u'', u'2', u'0', u'2', u'0', u'1', u'1', u'0', u'', u'0', u'1', u'0', u'1', u'1', u'', u'0', u'1', u'0', u'0', u'0'], [u'12', u'\n', u'Villarreal', u'2', u'', u'2', u'0', u'2', u'0', u'1', u'1', u'0', u'', u'0', u'1', u'0', u'0', u'0', u'', u'0', u'1', u'0', u'1', u'1'], [u'13', u'\n', u'Alav\xe9s', u'2', u'', u'2', u'0', u'2', u'0', u'1', u'1', u'0', u'', u'0', u'1', u'0', u'0', u'0', u'', u'0', u'1', u'0', u'1', u'1'], [u'14', u'\n', u'Espanyol', u'1', u'', u'2', u'0', u'1', u'1', u'6', u'8', u'-2', u'', u'0', u'1', u'0', u'2', u'2', u'', u'0', u'0', u'1', u'4', u'6'], [u'15', u'\n', u'Osasuna', u'1', u'', u'2', u'0', u'1', u'1', u'1', u'3', u'-2', u'', u'0', u'0', u'1', u'0', u'2', u'', u'0', u'1', u'0', u'1', u'1'], [u'16', u'\n', u'Granada', u'1', u'', u'2', u'0', u'1', u'1', u'2', u'6', u'-4', u'', u'0', u'1', u'0', u'1', u'1', u'', u'0', u'0', u'1', u'1', u'5'], [u'17', u'\n', u'Real Betis', u'1', u'', u'2', u'0', u'1', u'1', u'2', u'6', u'-4', u'', u'0', u'1', u'0', u'0', u'0', u'', u'0', u'0', u'1', u'2', u'6'], [u'18', u'\n', u'Celta Vigo', u'0', u'', u'2', u'0', u'0', u'2', u'1', u'3', u'-2', u'', u'0', u'0', u'1', u'0', u'1', u'', u'0', u'0', u'1', u'1', u'2'], [u'19', u'\n', u'Athletic Bilbao', u'0', u'', u'2', u'0', u'0', u'2', u'1', u'3', u'-2', u'', u'0', u'0', u'1', u'0', u'1', u'', u'0', u'0', u'1', u'1', u'2'], [u'20', u'\n', u'Valencia', u'0', u'', u'2', u'0', u'0', u'2', u'2', u'5', u'-3', u'', u'0', u'0', u'1', u'2', u'4', u'', u'0', u'0', u'1', u'0', u'1']]


Ahora si somos un poco curiosos( tenemos que!!! ), nos damos cuenta que hay campos que no queremos en nuestra nueva lista de listas y hay unos caracteres extraños como la "u" y la "u''" esto es especialmente importante la "u" creo que es unicode y las " u'' " con las comillas sin nada son campos que no contienen nada, por lo que no las necesitamos, ahora vamos a eliminar lo que no necesitamos con este código :D :

from prettytable import PrettyTable

tabla_pos = [[u'29 de agosto de 2016Primera Divisi\xf3n de Espa\xf1a 2016/2017 Tabla de posiciones'], [u'\xa0', u'\xa0', u'\xa0', u'General', u'', u'Local', u'', u'Visitante'], [u'Pos.', u'', u'EQUIPO', u'Pts.', u'', u'PJ', u'G', u'E', u'P', u'GF', u'GC', u'Dif.', u'', u'G', u'E', u'P', u'GF', u'GC', u'', u'G', u'E', u'P', u'GF', u'GC'], [u'1', u'\n', u'Las Palmas', u'6', u'', u'2', u'2', u'0', u'0', u'9', u'3', u'6', u'', u'1', u'0', u'0', u'5', u'1', u'', u'1', u'0', u'0', u'4', u'2'], [u'2', u'\n', u'Barcelona', u'6', u'', u'2', u'2', u'0', u'0', u'7', u'2', u'5', u'', u'1', u'0', u'0', u'6', u'2', u'', u'1', u'0', u'0', u'1', u'0'], [u'3', u'\n', u'Real Madrid', u'6', u'', u'2', u'2', u'0', u'0', u'5', u'1', u'4', u'', u'1', u'0', u'0', u'2', u'1', u'', u'1', u'0', u'0', u'3', u'0'], [u'4', u'\n', u'Sevilla FC', u'4', u'', u'2', u'1', u'1', u'0', u'6', u'4', u'2', u'', u'1', u'0', u'0', u'6', u'4', u'', u'0', u'1', u'0', u'0', u'0'], [u'5', u'\n', u'Sporting Gij\xf3n', u'4', u'', u'2', u'1', u'1', u'0', u'2', u'1', u'1', u'', u'1', u'0', u'0', u'2', u'1', u'', u'0', u'1', u'0', u'0', u'0'], [u'6', u'\n', u'Deportivo La Coru\xf1a', u'4', u'', u'2', u'1', u'1', u'0', u'2', u'1', u'1', u'', u'1', u'0', u'0', u'2', u'1', u'', u'0', u'1', u'0', u'0', u'0'], [u'7', u'\n', u'Leganes', u'4', u'', u'2', u'1', u'1', u'0', u'1', u'0', u'1', u'', u'0', u'1', u'0', u'0', u'0', u'', u'1', u'0', u'0', u'1', u'0'], [u'8', u'\n', u'Eibar', u'3', u'', u'2', u'1', u'0', u'1', u'2', u'2', u'0', u'', u'1', u'0', u'0', u'1', u'0', u'', u'0', u'0', u'1', u'1', u'2'], [u'9', u'\n', u'Real Sociedad', u'3', u'', u'2', u'1', u'0', u'1', u'2', u'3', u'-1', u'', u'0', u'0', u'1', u'0', u'3', u'', u'1', u'0', u'0', u'2', u'0'], [u'10', u'\n', u'M\xe1laga', u'2', u'', u'2', u'0', u'2', u'0', u'3', u'3', u'0', u'', u'0', u'1', u'0', u'1', u'1', u'', u'0', u'1', u'0', u'2', u'2'], [u'11', u'\n', u'Atletico Madrid', u'2', u'', u'2', u'0', u'2', u'0', u'1', u'1', u'0', u'', u'0', u'1', u'0', u'1', u'1', u'', u'0', u'1', u'0', u'0', u'0'], [u'12', u'\n', u'Villarreal', u'2', u'', u'2', u'0', u'2', u'0', u'1', u'1', u'0', u'', u'0', u'1', u'0', u'0', u'0', u'', u'0', u'1', u'0', u'1', u'1'], [u'13', u'\n', u'Alav\xe9s', u'2', u'', u'2', u'0', u'2', u'0', u'1', u'1', u'0', u'', u'0', u'1', u'0', u'0', u'0', u'', u'0', u'1', u'0', u'1', u'1'], [u'14', u'\n', u'Espanyol', u'1', u'', u'2', u'0', u'1', u'1', u'6', u'8', u'-2', u'', u'0', u'1', u'0', u'2', u'2', u'', u'0', u'0', u'1', u'4', u'6'], [u'15', u'\n', u'Osasuna', u'1', u'', u'2', u'0', u'1', u'1', u'1', u'3', u'-2', u'', u'0', u'0', u'1', u'0', u'2', u'', u'0', u'1', u'0', u'1', u'1'], [u'16', u'\n', u'Granada', u'1', u'', u'2', u'0', u'1', u'1', u'2', u'6', u'-4', u'', u'0', u'1', u'0', u'1', u'1', u'', u'0', u'0', u'1', u'1', u'5'], [u'17', u'\n', u'Real Betis', u'1', u'', u'2', u'0', u'1', u'1', u'2', u'6', u'-4', u'', u'0', u'1', u'0', u'0', u'0', u'', u'0', u'0', u'1', u'2', u'6'], [u'18', u'\n', u'Celta Vigo', u'0', u'', u'2', u'0', u'0', u'2', u'1', u'3', u'-2', u'', u'0', u'0', u'1', u'0', u'1', u'', u'0', u'0', u'1', u'1', u'2'], [u'19', u'\n', u'Athletic Bilbao', u'0', u'', u'2', u'0', u'0', u'2', u'1', u'3', u'-2', u'', u'0', u'0', u'1', u'0', u'1', u'', u'0', u'0', u'1', u'1', u'2'], [u'20', u'\n', u'Valencia', u'0', u'', u'2', u'0', u'0', u'2', u'2', u'5', u'-3', u'', u'0', u'0', u'1', u'2', u'4', u'', u'0', u'0', u'1', u'0', u'1']]
 
i = 0

tabla_formateada = []

nueva_form = []

for datos  in tabla_pos:
  
    if i >= 3:
        while (u'' or u'\n')  in datos:
            if (u'')  in datos :
                datos.remove(u'')
            elif  u'\n'  in datos:
	       datos.remove(u'\n')
        
        tabla_formateada.append(datos)
        
        nueva_form = tabla_formateada

    i += 1        

print nueva_form


Si nos fijamos en el código:


No estamos haciendo scraping aun. Simplemente traslade la salida del programa anterior a texto plano para visualizarlo rápido.


Como mi Internet es limitado no quiero estar bajando 200 veces lo mismo, esta salida que teníamos ahora la vamos a filtrar. Lo primero que hacemos es inicial izar la variable i =0.


Creamos 2 listas para trabajar en ellas, y creamos un bucle FOR con 3 propósitos.  

El primero para eliminar las 3 listas iniciales ya que contienen información irrelevante lo hacemos con "if i >=3:". 

El segundo para eliminar los campos en blanco o con caracteres medio raros como "u'\n'".  

Y el tercer propósito crear una nueva lista formateada con los datos que si queremos :D, esta es la salida:

[[u'1', u'Las Palmas', u'6', u'2', u'2', u'0', u'0', u'9', u'3', u'6', u'1', u'0', u'0', u'5', u'1', u'1', u'0', u'0', u'4', u'2'], [u'2', u'Barcelona', u'6', u'2', u'2', u'0', u'0', u'7', u'2', u'5', u'1', u'0', u'0', u'6', u'2', u'1', u'0', u'0', u'1', u'0'], [u'3', u'Real Madrid', u'6', u'2', u'2', u'0', u'0', u'5', u'1', u'4', u'1', u'0', u'0', u'2', u'1', u'1', u'0', u'0', u'3', u'0'], [u'4', u'Sevilla FC', u'4', u'2', u'1', u'1', u'0', u'6', u'4', u'2', u'1', u'0', u'0', u'6', u'4', u'0', u'1', u'0', u'0', u'0'], [u'5', u'Sporting Gij\xf3n', u'4', u'2', u'1', u'1', u'0', u'2', u'1', u'1', u'1', u'0', u'0', u'2', u'1', u'0', u'1', u'0', u'0', u'0'], [u'6', u'Deportivo La Coru\xf1a', u'4', u'2', u'1', u'1', u'0', u'2', u'1', u'1', u'1', u'0', u'0', u'2', u'1', u'0', u'1', u'0', u'0', u'0'], [u'7', u'Leganes', u'4', u'2', u'1', u'1', u'0', u'1', u'0', u'1', u'0', u'1', u'0', u'0', u'0', u'1', u'0', u'0', u'1', u'0'], [u'8', u'Eibar', u'3', u'2', u'1', u'0', u'1', u'2', u'2', u'0', u'1', u'0', u'0', u'1', u'0', u'0', u'0', u'1', u'1', u'2'], [u'9', u'Real Sociedad', u'3', u'2', u'1', u'0', u'1', u'2', u'3', u'-1', u'0', u'0', u'1', u'0', u'3', u'1', u'0', u'0', u'2', u'0'], [u'10', u'M\xe1laga', u'2', u'2', u'0', u'2', u'0', u'3', u'3', u'0', u'0', u'1', u'0', u'1', u'1', u'0', u'1', u'0', u'2', u'2'], [u'11', u'Atletico Madrid', u'2', u'2', u'0', u'2', u'0', u'1', u'1', u'0', u'0', u'1', u'0', u'1', u'1', u'0', u'1', u'0', u'0', u'0'], [u'12', u'Villarreal', u'2', u'2', u'0', u'2', u'0', u'1', u'1', u'0', u'0', u'1', u'0', u'0', u'0', u'0', u'1', u'0', u'1', u'1'], [u'13', u'Alav\xe9s', u'2', u'2', u'0', u'2', u'0', u'1', u'1', u'0', u'0', u'1', u'0', u'0', u'0', u'0', u'1', u'0', u'1', u'1'], [u'14', u'Espanyol', u'1', u'2', u'0', u'1', u'1', u'6', u'8', u'-2', u'0', u'1', u'0', u'2', u'2', u'0', u'0', u'1', u'4', u'6'], [u'15', u'Osasuna', u'1', u'2', u'0', u'1', u'1', u'1', u'3', u'-2', u'0', u'0', u'1', u'0', u'2', u'0', u'1', u'0', u'1', u'1'], [u'16', u'Granada', u'1', u'2', u'0', u'1', u'1', u'2', u'6', u'-4', u'0', u'1', u'0', u'1', u'1', u'0', u'0', u'1', u'1', u'5'], [u'17', u'Real Betis', u'1', u'2', u'0', u'1', u'1', u'2', u'6', u'-4', u'0', u'1', u'0', u'0', u'0', u'0', u'0', u'1', u'2', u'6'], [u'18', u'Celta Vigo', u'0', u'2', u'0', u'0', u'2', u'1', u'3', u'-2', u'0', u'0', u'1', u'0', u'1', u'0', u'0', u'1', u'1', u'2'], [u'19', u'Athletic Bilbao', u'0', u'2', u'0', u'0', u'2', u'1', u'3', u'-2', u'0', u'0', u'1', u'0', u'1', u'0', u'0', u'1', u'1', u'2'], [u'20', u'Valencia', u'0', u'2', u'0', u'0', u'2', u'2', u'5', u'-3', u'0', u'0', u'1', u'2', u'4', u'0', u'0', u'1', u'0', u'1']]

Ahora para terminar esta entrada, en la siguiente vamos a retomar cosas interesantes de este mismo proyecto, vamos a mostrar los datos en una tabla, pero no todos los datos solo 4, este es el código


numero_items = len(nueva_form[0])
print numero_items



table = PrettyTable(["Posicion", "Equipo", "Puntos", "Dif_Gol"])
i = 0
for i in range(0,numero_items):
    if i >= 0:
        table.add_row([nueva_form[i][0], nueva_form[i][1], nueva_form[i][2] , nueva_form[i][9]])

    i += 0
    
print table


Recuerda enlazar este código a el anterior, La salida de este Trozo de Código es esta:

20
+----------+---------------------+--------+---------+
| Posicion |        Equipo       | Puntos | Dif_Gol |
+----------+---------------------+--------+---------+
|    1     |      Las Palmas     |   6    |    6    |
|    2     |      Barcelona      |   6    |    5    |
|    3     |     Real Madrid     |   6    |    4    |
|    4     |      Sevilla FC     |   4    |    2    |
|    5     |    Sporting Gijón   |   4    |    1    |
|    6     | Deportivo La Coruña |   4    |    1    |
|    7     |       Leganes       |   4    |    1    |
|    8     |        Eibar        |   3    |    0    |
|    9     |    Real Sociedad    |   3    |    -1   |
|    10    |        Málaga       |   2    |    0    |
|    11    |   Atletico Madrid   |   2    |    0    |
|    12    |      Villarreal     |   2    |    0    |
|    13    |        Alavés       |   2    |    0    |
|    14    |       Espanyol      |   1    |    -2   |
|    15    |       Osasuna       |   1    |    -2   |
|    16    |       Granada       |   1    |    -4   |
|    17    |      Real Betis     |   1    |    -4   |
|    18    |      Celta Vigo     |   0    |    -2   |
|    19    |   Athletic Bilbao   |   0    |    -2   |
|    20    |       Valencia      |   0    |    -3   |
+----------+---------------------+--------+---------+


El código completo y funcionando del programa que hemos hecho es este:


import urllib2
from bs4 import BeautifulSoup
import re
from prettytable import PrettyTable

# url that we are scraping
url = "http://www.espn.com.ve/futbol/posicionesenvivo/_/liga/esp.1/primera-division-de-espana"

page = urllib2.urlopen(url)

soup = BeautifulSoup(page, "lxml")


table = soup.find('table')

rows = table.find_all('tr')
results = []

for row in rows:
        table_headers = row.find_all('th')
        if table_headers:
            results.append([headers.get_text() for headers in table_headers])

        table_data = row.find_all('td')
        if table_data:
	    results.append([data.get_text() for data in table_data])






tabla_pos = results

i = 0

tabla_formateada = []

nueva_form = []

for datos  in tabla_pos:
  
    if i >= 3:
        while (u'' or u'\n')  in datos:
            if (u'')  in datos :
                datos.remove(u'')
            elif  u'\n'  in datos:
	       datos.remove(u'\n')
        
        tabla_formateada.append(datos)
        
        nueva_form = tabla_formateada

    i += 1        



numero_items = len(nueva_form[0])



table = PrettyTable(["Posicion", "Equipo", "Puntos", "Dif_Gol"])
i = 0
for i in range(0,numero_items):
    if i >= 0:
        table.add_row([nueva_form[i][0], nueva_form[i][1], nueva_form[i][2] , nueva_form[i][9]])

    i += 0
    
print table


Y la salida es esta:

+----------+---------------------+--------+---------+
| Posicion |        Equipo       | Puntos | Dif_Gol |
+----------+---------------------+--------+---------+
|    1     |      Las Palmas     |   6    |    6    |
|    2     |      Barcelona      |   6    |    5    |
|    3     |     Real Madrid     |   6    |    4    |
|    4     |      Sevilla FC     |   4    |    2    |
|    5     |    Sporting Gijón   |   4    |    1    |
|    6     | Deportivo La Coruña |   4    |    1    |
|    7     |       Leganes       |   4    |    1    |
|    8     |        Eibar        |   3    |    0    |
|    9     |    Real Sociedad    |   3    |    -1   |
|    10    |        Málaga       |   2    |    0    |
|    11    |   Atletico Madrid   |   2    |    0    |
|    12    |      Villarreal     |   2    |    0    |
|    13    |        Alavés       |   2    |    0    |
|    14    |       Espanyol      |   1    |    -2   |
|    15    |       Osasuna       |   1    |    -2   |
|    16    |       Granada       |   1    |    -4   |
|    17    |      Real Betis     |   1    |    -4   |
|    18    |      Celta Vigo     |   0    |    -2   |
|    19    |   Athletic Bilbao   |   0    |    -2   |
|    20    |       Valencia      |   0    |    -3   |
+----------+---------------------+--------+---------+

Gracias hasta la próxima que Dios les Bendiga, hasta la proxima :D

Sort:  

It's very interesting post!!
Great job dear @sethroot :)

gracias amigo, estoy pensando en mejorar otros codigos que tengo a mano :D
Thanks friend, I am thinking of improving other codes that I have at hand :D