Scraping con Python, Liga BBVA de ESPN [Parte 1]
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
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