Web scraping con python

Web scraping con python

Scrapping web con python y beautifulsoup

Como vimos en el post de “Html scraping en php con curl” en esta ocasión lo hacemos con python, ademas de eso le he añadido el plus de utilizar el modulo xlwt para escribir en hojas de calculo como la de libreoffice calc pero sirve para otras como excel etc…

Vamos a hacer lo mismo que hicimos en post de scraping con php sacaremos últimos sorteos de lotería.

Vamos con el código.

# -*- coding: utf-8 -*-

# Módulo con el que haremos el scraping
from bs4 import BeautifulSoup

# Importamos request para obtener la página
import requests

# Time y calendar lo usaremos para formatear y obtener fechas
import time
import calendar
from calendar import monthrange, weekday, day_name

# Y usaremos estas dos clases de xlwt para crear nuestro documento calc o excel
from xlwt import Workbook, easyxf

Vale, una vez importados estos módulos necesarios para trabajar vamos a empezar creando primero el documento excel con sus atributos para guardar los datos ( también podríamos hacer en una base datos, en un documento de text o en un pdf)

# Creamos nuestra hoja de calculo
first_book=Workbook()

#easyxf lo usaremos para aplicar estilos a las celdas
fmt = easyxf

# Estilos principales de las celdas
encabezado = fmt('font: bold on, color white, height 230; alignment: horiz centre;borders: top_color black, bottom_color black, right_color black, left_color black,\
				 left thin, right thin, top thin, bottom thin;\
				 pattern: pattern solid, fore_color gray25;')
fecha_estilo = fmt('font: bold on,color orange; alignment: horiz centre;borders: top_color black, bottom_color black, right_color black, left_color black,\
				 left thin, right thin, top thin, bottom thin;\
				 pattern: pattern solid, fore_color white;')
normal = fmt('font: bold on; alignment: horiz centre;borders: top_color black, bottom_color black, right_color black, left_color black,\
				 left thin, right thin, top thin, bottom thin;\
				 pattern: pattern solid, fore_color white;')

# Definimos el nombre de sheet
ws1 = first_book.add_sheet('resultados_primitva')

# Asignamos las primeras celdas que serán las cabeceras
# Usamos write(columna, fila, dato, estilo) para definir cada celda
# Usamos col('columna').width(x) para definir la anchura de la celda
ws1.write(0, 0, 'Fecha', encabezado)
ws1.col(0).width = int(len('fecha')*500)  
ws1.write(0, 1, 'Sorteo', encabezado)
ws1.col(1).width = int(len('Sorteo')*500)  
ws1.write(0, 2, 'Complementario', encabezado)
ws1.col(2).width = int(len('Complementario')*500)  
ws1.write(0, 3, 'Reintegro', encabezado)
ws1.col(3).width = int(len('Reintegro')*500)  
ws1.write(0, 4, 'Joker', encabezado)
ws1.col(4).width = int(len('Joker')*500)

Con esto ya tenemos definido la primera parte del documento, ahora vamos a definir una función que obtiene el dato del sorteo

#A la función le vamos a pasar el dia, mes y año en número y el día en texto
def get_resultado(dia, mes, ano, nombre_dia):
        # Traducimos ya que es necesario para formatear la url
	if (nombre_dia == "Saturday"):
		nombre_dia = "sabado"
	else:
		nombre_dia = "jueves"

        # Añadimos un 0 delante a números menores a diez para formatear la url
	if dia<10:
		dia = "0{0}".format(dia)
	if mes<10:
		mes = "0{0}".format(mes)
        
        #Formateo de la url a scrapear
	URL = "http://www.laprimitiva.info/loteriaprimitiva/Sorteo-{0}-{1}-{2}-{3}.html".format(dia, mes, ano, nombre_dia)	
	

	# Realizamos la petición a la web
	req = requests.get(URL)

	# Comprobamos que la petición nos devuelve un Status Code = 200
	status_code = req.status_code
	if status_code == 200:
		
		# Pasamos el contenido HTML de la web a un objeto BeautifulSoup()
		html = BeautifulSoup(req.text, "html.parser")
		
		# Creamos un diccionario de resultados
		resultado = {'fecha':"{0}/{1}/{2}".format(dia, mes, ano)}
		
		# Vamos a comparar la fecha para saber si existe este resultado
                # Si no existe devolvemos un false y evitamos guardar datos inútiles
                # Si existe scrapreamos
		get_fecha = html.find('div', {'class':'grid_9 fechasorteo'}).getText()[14:]
		if (get_fecha != '{0}-{1}-{2}'.format(dia,mes,ano)):
			return False
		else:

			# Obtenemos todos los li de los números del sorteo
			get_sorteo = html.find_all('li', {'class': 'circuloverde'})
			
			# Añadimos cada número del sorteo a una lista
			sorteo = []

			# Recorremos los li obtenidos para añadirlos a lista
			for i in get_sorteo:
				sorteo.append( i.getText() ) 
 
			#Añadimos a nuestro diccionario la lista del sorteo
			resultado['sorteo'] = sorteo
			
			#Obtenemos el div del número complementario
			complementario = html.find('div', {'class': 'circulonaranja'})
			complementario = complementario.getText()

                        #Añadimos el complementario al diccionario
			resultado['complementario'] = complementario
			
			#Obtenemos el div del numero reintegro
			reintegro = html.find('div', {'class': 'circuloverder'})
			reintegro = reintegro.getText()
             
                        #Añadimos el reintegro al diccionario
			resultado['reintegro'] = reintegro

			#Obtenemos el div del numero joker
			joker = html.find('span', {'class': 'joker'})
			joker = joker.getText()
                        
                        #Eliminamos los seis primeros caracteres que son inútiles
			joker = joker[6:]
                        
                        #Añadimos al diccionario el joker
			resultado['joker'] = joker
           
                        #Devolvemos nuestro diccionario completo
			return resultado
		 
	else:
		print "Status Code %d" % status_code
		return False

Bien el primer trabajo importante esta hecho con esta función, ahora solo queda recorrer unas cuantas fechas para obtener múltiples sorteos y añadirlos a la hoja de calculo.

#Declaramos las variables de las fechas
# El día mes y año por el cual queremos que empiece
dia_inicio = 1
mes_inicio = 1
ano_inicio = 2017

# Declaramos las fechas actuales como limite del loop
dia_actual = int(time.strftime("%d"))
mes_actual = int(time.strftime("%m"))
ano_actual = int(time.strftime("%Y"))

# Esta celda corresponderá a la file que ira aumentando en cada resultado correcto
celda_count = 0

# Creamos un loop while que se romperá si superamos nuestra fecha limite que es la actual
while True:
        # Guardamos en una variable en nombre en texto del dia
	nombre_dia = day_name[ weekday(ano_inicio, mes_inicio, dia_inicio) ]

        # Guardamos en esta variable el número de días que tiene el mes
	dias_mes = monthrange(ano_inicio, mes_inicio)[1]

        # Si es jueves o sábado que son las fechas en las que hay primitiva ejecutamos nuestra función anterior
	if ( nombre_dia == "Saturday" or nombre_dia == "Thursday" ):
                
 
                #Almacenamos el resultado en la variable resultado con nuestra función
		resultado = get_resultado(dia_inicio, mes_inicio, ano_inicio, nombre_dia)

                # Si el resultado existe, es decir sino nos devuelve false escribimos en el documento
		if (resultado):
                         # Sumamos uno a nuestra fila para escribir en la siguiente
		        celda_count +=1

			ws1.write(celda_count, 0, resultado['fecha'], fecha_estilo)
			ws1.write(celda_count, 1, resultado['sorteo'], normal)
			ws1.col(1).width = int(len(resultado['sorteo'])*600)
			ws1.write(celda_count, 2, resultado['complementario'], normal)
			ws1.write(celda_count, 3, resultado['reintegro'], normal)
			ws1.write(celda_count, 4, resultado['joker'], normal)
			print "Obteniendo resultado del {0}\n".format(resultado['fecha'])

        #Sumamos un día para la siguiente fecha a scrapear
	dia_inicio +=1

       # Si el día es mayor a la cantidad de días que tiene el mes, le asignamos el día 1 y sumamos un día al mes
	if (dia_inicio>dias_mes):
		dia_inicio = 1
		mes_inicio +=1

        # Si el mes es mayor a doce, le asignamos mes 1 y sumamos uno al año
	if (mes_inicio>12):
		mes_inicio = 1
		ano_inicio = 1

        # Si superamos la fecha del día de hoy rompemos el loop
	if (dia_inicio>dia_actual and mes_inicio >= mes_actual and ano_inicio >= ano_actual):
		break
	

# Por último guardamos nuestro documento
first_book.save('resultados_primitiva.xls')

# -*- coding: utf-8 -*-

# Módulo con el que haremos el scraping
from bs4 import BeautifulSoup

# Importamos request para obtener la página
import requests

# Time y calendar lo usaremos para formatear y obtener fechas
import time
import calendar
from calendar import monthrange, weekday, day_name

# Y usaremos estas dos clases de xlwt para crear nuestro documento calc o excel
from xlwt import Workbook, easyxf

# Creamos nuestra hoja de calculo
first_book=Workbook()

#easyxf lo usaremos para aplicar estilos a las celdas
fmt = easyxf

# Estilos principales de las celdas
encabezado = fmt('font: bold on, color white, height 230; alignment: horiz centre;borders: top_color black, bottom_color black, right_color black, left_color black,\
				 left thin, right thin, top thin, bottom thin;\
				 pattern: pattern solid, fore_color gray25;')
fecha_estilo = fmt('font: bold on,color orange; alignment: horiz centre;borders: top_color black, bottom_color black, right_color black, left_color black,\
				 left thin, right thin, top thin, bottom thin;\
				 pattern: pattern solid, fore_color white;')
normal = fmt('font: bold on; alignment: horiz centre;borders: top_color black, bottom_color black, right_color black, left_color black,\
				 left thin, right thin, top thin, bottom thin;\
				 pattern: pattern solid, fore_color white;')

# Definimos el nombre de sheet
ws1 = first_book.add_sheet('resultados_primitva')

# Asignamos las primeras celdas que serán las cabeceras
# Usamos write(columna, fila, dato, estilo) para definir cada celda
# Usamos col('columna').width(x) para definir la anchura de la celda
ws1.write(0, 0, 'Fecha', encabezado)
ws1.col(0).width = int(len('fecha')*500)  
ws1.write(0, 1, 'Sorteo', encabezado)
ws1.col(1).width = int(len('Sorteo')*500)  
ws1.write(0, 2, 'Complementario', encabezado)
ws1.col(2).width = int(len('Complementario')*500)  
ws1.write(0, 3, 'Reintegro', encabezado)
ws1.col(3).width = int(len('Reintegro')*500)  
ws1.write(0, 4, 'Joker', encabezado)
ws1.col(4).width = int(len('Joker')*500)

#A la función le vamos a pasarel día, mes y año en número y el día en texto
def get_resultado(dia, mes, ano, nombre_dia):
        # Traducimos ya que es necesario para formatear la url
	if (nombre_dia == "Saturday"):
		nombre_dia = "sabado"
	else:
		nombre_dia = "jueves"

        # Añadimos un 0 delante a números menores a diez para formatear la url
	if dia<10:
		dia = "0{0}".format(dia)
	if mes<10:
		mes = "0{0}".format(mes)
        
        #Formateo de la url a scrapear
	URL = "http://www.laprimitiva.info/loteriaprimitiva/Sorteo-{0}-{1}-{2}-{3}.html".format(dia, mes, ano, nombre_dia)	
	

	# Realizamos la petición a la web
	req = requests.get(URL)

	# Comprobamos que la petición nos devuelve un Status Code = 200
	status_code = req.status_code
	if status_code == 200:
		
		# Pasamos el contenido HTML de la web a un objeto BeautifulSoup()
		html = BeautifulSoup(req.text, "html.parser")
		
		# Creamos un diccionario de resultados
		resultado = {'fecha':"{0}/{1}/{2}".format(dia, mes, ano)}
		
		# Vamos a comparar la fecha para saber si existe este resultado
                # Si no existe devolvemos un false y evitamos guardar datos inútiles
                # Si existe scrapreamos
		get_fecha = html.find('div', {'class':'grid_9 fechasorteo'}).getText()[14:]
		if (get_fecha != '{0}-{1}-{2}'.format(dia,mes,ano)):
			return False
		else:

			# Obtenemos todos los li de los números del sorteo
			get_sorteo = html.find_all('li', {'class': 'circuloverde'})
			
			# Añadimos cada número del sorteo a una lista
			sorteo = []

			# Recorremos los li obtenidos para añadirlos a lista
			for i in get_sorteo:
				sorteo.append( i.getText() ) 
 
			#Añadimos a nuestro diccionario la lista del sorteo
			resultado['sorteo'] = sorteo
			
			#Obtenemos el div del número complementario
			complementario = html.find('div', {'class': 'circulonaranja'})
			complementario = complementario.getText()

                        #Añadimos el complementario al diccionario
			resultado['complementario'] = complementario
			
			#Obtenemos el div del numero reintegro
			reintegro = html.find('div', {'class': 'circuloverder'})
			reintegro = reintegro.getText()
             
                        #Añadimos el reintegro al diccionario
			resultado['reintegro'] = reintegro

			#Obtenemos el div del numero joker
			joker = html.find('span', {'class': 'joker'})
			joker = joker.getText()
                        
                        #Eliminamos los seis primeros caracteres que son inútiles
			joker = joker[6:]
                        
                        #Añadimos al diccionario el joker
			resultado['joker'] = joker
           
                        #Devolvemos nuestro diccionario completo
			return resultado
		 
	else:
		print "Status Code %d" % status_code
		return False

#Declaramos las variables de las fechas
# El día mes y año por el cual queremos que empiece
dia_inicio = 1
mes_inicio = 1
ano_inicio = 2017

# Declaramos las fechas actuales como limite del loop
dia_actual = int(time.strftime("%d"))
mes_actual = int(time.strftime("%m"))
ano_actual = int(time.strftime("%Y"))

# Esta celda correspondera a la file que ira aumentando en cada resultado correcto
celda_count = 0

# Creamos un loop while que se romperá si superamos nuestra fecha limite que es la actual
while True:
        # Guardamos en una variable en nombre en texto del dia
	nombre_dia = day_name[ weekday(ano_inicio, mes_inicio, dia_inicio) ]

        # Guardamos en esta variable el número de días que tiene el mes
	dias_mes = monthrange(ano_inicio, mes_inicio)[1]

        # Si es jueves o sábado que son las fechas en las que hay primitiva ejecutamos nuestra función anterior
	if ( nombre_dia == "Saturday" or nombre_dia == "Thursday" ):
                
 
                #Almacenamos el resultado en la variable resultado con nuestra función
		resultado = get_resultado(dia_inicio, mes_inicio, ano_inicio, nombre_dia)

                # Si el resultado existe, es decir sino nos devuelve false escribimos en el documento
		if (resultado):
                         # Sumamos uno a nuestra fila para escribit en la siguiente
		        celda_count +=1

			ws1.write(celda_count, 0, resultado['fecha'], fecha_estilo)
			ws1.write(celda_count, 1, resultado['sorteo'], normal)
			ws1.col(1).width = int(len(resultado['sorteo'])*600)
			ws1.write(celda_count, 2, resultado['complementario'], normal)
			ws1.write(celda_count, 3, resultado['reintegro'], normal)
			ws1.write(celda_count, 4, resultado['joker'], normal)
			print "Obteniendo resultado del {0}\n".format(resultado['fecha'])

        #Sumamos un día para la siguiente fecha a scrapear
	dia_inicio +=1

       # Si el día es mayor a la cantidad de días que tiene el mes, le asignamos el día 1 y sumamos un día al mes
	if (dia_inicio>dias_mes):
		dia_inicio = 1
		mes_inicio +=1

        # Si el mes es mayor a doce, le asignamos mes 1 y sumamos uno al año
	if (mes_inicio>12):
		mes_inicio = 1
		ano_inicio = 1

        # Si superamos la fecha del día de hoy rompemos el loop
	if (dia_inicio>dia_actual and mes_inicio >= mes_actual and ano_inicio >= ano_actual):
		break
	

# Por último guardamos nuestro documento
first_book.save('resultados_primitiva.xls')

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Pin It on Pinterest