Anuncios

Bienvenidos sean a este post, en el post anterior creamos toda la interfaz o GUI para el programa pero le agregaremos todas las funciones de cada elemento.

Anuncios

Buscar paginas

En el post anterior creamos todos los elementos que veremos en la ventana pero ninguno tiene alguna accion por el momento, en este post agregaremos todas las funciones necesarias para poder utilizarlos, comencemos agregando la primera:

config = {}

def buscar_url():
	url = _url.get()
	config['imagenes'] = []
	_imagenes.set(())
	try:
		pagina = requests.get(url)
	except requests.RequestException as err:
		estado(str(err))
	else:
		sopa = BeautifulSoup(pagina.content, 'html.parser')
		imagenes = buscar_imagenes(sopa, url)
		if imagenes:
			_imagenes.set(tuple(img['nombre']
				for img in imagenes))
			estado('Imagenes encontradas: {}'
			.format(len(imagenes)))
		else:
			estado('Imagenes no encontradas')
		config['imagenes'] = imagenes
Anuncios
Anuncios

Primero definiremos un diccionario global llamado config, luego definiremos la funcion buscar_url que sera la encargada de buscar el contenido de la pagina, primero obtendremos la url informada en el elemento Entry llamado _url, luego iniciamos un campo llamado imagenes en config por el momento vacio y por ultimo reiniciaremos a _imagenes por medio de un set en blanco, en un try cargaremos todo el contenido de la URL informada por medio del get de requests en un objeto llamado pagina, y el except lo usaremos por si sale un excepcion de tipo RequestException y en caso de ocurrir mostraremos en el cuadro de estado el valor obtenido.

Anuncios
Anuncios

Lo siguiente es un else muy parecido al visto en el script, primero crearemos el objeto de tipo BeautifulSoup donde recibira todo el contenido almacenado en pagina y le pasamos el tipo de parser que usaremos, crearemos un objeto llamado imagenes y usaremos a buscar_imagenes pero de esta hablaremos luego, lo siguiente es un condicional donde verifica que imagenes se haya generado o tenga un contenido, en caso de ser verdadero le agregaremos un tuple donde agregaremos los nombres de todas las imagenes agregadas, luego usaremos una funcion llamada estado donde le pasaremos un texto que nos diran cuantas fotos fueron encontradas, de lo contrario le pasaremos a estado un texto donde informaremos que no encontro ninguna, en cualquier caso pasaremos a imagenes a la clave imagenes de config, con esto terminamos la funcion ahora continuemos agregando la siguiente funcion:

def buscar_imagenes(sopa, url_base):
	imagenes = []
	for img in sopa.findAll('img'):
		fnt = img.get('src')
		url_img = f'{url_base}/{fnt}'
		nombre = url_img.split('/')[-1]
		imagenes.append(dict(nombre=nombre, url=url_img))
	return imagenes
Anuncios
Anuncios

Esta es una de las dos funciones que mencionamos anteriormente y se encargara de buscarnos todas las imagenes de la pagina que informemos, para este caso pasamos el objeto creado por BeautifulSoup y la url base que informamos, tecnicamente es el mismo codigo que vimos en este post pero resumiendolo busca los tags de img, extrae el valor de src lo une con la url base, obtiene el nombre del archivo y lo agrega a imagenes, una vez finalizado procede a devolver ese diccionario, con esto ya tenemos las funciones que buscan el contenido de la pagina y las imagenes dentro de ella para procesarlas, mostrarlas en el listbox de las imagenes y en estado mostrar la cantidad.

Anuncios

Guardar imagenes

Nuestro siguiente paso sera agregar la funcion que se encarga de grabar las imagenes obtenidas, pasemos a agregar el siguiente codigo:

def guardar():
	if not config.get('imagenes'):
		estado('No hay imagenes para grabar')
		return

	if _metodo_guardar.get() == 'img':
		nombredir = filedialog.askdirectory(mustexist=True)
		guardar_imagenes(nombredir)
	else:
		archivo = filedialog.asksaveasfilename(
			initialfile='imagenes.json',
			filetypes=[('JSON', '.json')])
		guardar_json(archivo)
Anuncios
Anuncios

Esta funcion sera la principal para guardar los archivos que buscamos en la pagina web informada, en caso de no existir un valor en la clave imagenes de config devolvemos un mensaje en estado informando que no hay imagenes para grabar, despues verificamos si el valor en _metodo_guardar es igual a ‘img’ significa que deseamos descargar todas las imagenes por lo tanto creamos un objeto llamado nombredir donde utilizaremos a filedialog y askdirectory , con la opcion mustexist como True para indicar que este debe existir, esta funcion nos abrira un cuadro de dialogo para indicar en que directorio descargaremos todas las imagenes, lo siguiente sera llamar a una funcion que definiremos a continuacion informando el objeto nombredir que definimos anteriormente, en caso contrario crearemos un objeto llamado archivo donde de vuelta usaremos a filedialog pero esta vez con asksaveasfilename, al cual informaremos el parametro initialfile y filetypes con el nombre del archivo y las extensiones disponibles respectivamente, la cual nos abrira un cuadro de dialogo pero para guardar nuestro archivo, por ultimo llamamos a una funcion que definiremos despues de la anterior, pasemos a definir la funcion encargada de guardar los archivos:

def guardar_imagenes(nombredir):
	if nombredir and config.get('imagenes'):
		for img in config['imagenes']:
			datos_img = requests.get(img['url']).content
			archivo = os.path.join(nombredir, img['nombre'])
			with open(archivo, 'wb') as f:
				f.write(datos_img)
		estado('Hecho')
Anuncios
Anuncios

Como dijimos antes pasamos el objeto conteniendo nuestra carpeta de destino, usamos un condicional donde verificamos que exista un directorio y contenido dentro de config, en la clave imagenes mas exactamente, y en caso de ser verdadero procede a usar un bucle for donde pasa por todos los elementos de imagenes en config, creamos un nuevo objeto que almacenara el contenido de la pagina informada en url, otra clave de img, el siguiente objeto sera el archivo donde guardaremos la imagen, para ello unimos el directorio que elegimos junto al nombre del archivo que posee la clave nombre, por ultimo usamos un with con open para almacenar todo el contenido almacenado en datos_img, por ultimo enviamos un mensaje de realizado al estado, funcion que definiremos despues de la siguiente, con esto concluimos con la funcion para guardar imagenes pasemos a definir la funcion encargada de almacenar el JSON:

def guardar_json(archivo):
	if archivo and config.get('imagenes'):
		datos = {}
		for img in config['imagenes']:
			datos_img = requests.get(img['url']).content
			datos_img_b64 = base64.b64encode(datos_img)
			datos_img_str = datos_img_b64.decode('utf-8')
			datos[img['nombre']] = datos_img_str

		with open(archivo, 'w') as ijson:
			ijson.write(json.dumps(datos))
		estado('Hecho')
Anuncios
Anuncios

Esta funcion como dijimos sera la encargada de crear el archivo JSON y almacenar toda la informacion en la misma, esta trabaja de la misma forma que vimos en este post, la unica diferencia radica en que tendremos un condicional que verifica la existencia de un archivo para recibirlo y que config contenga la clave imagenes con los datos a escribir, el resto es exactamente lo mismo a lo citado en este post pero resumiendolo pasa por todas las imagenes, obtiene el contenido de cada pagina, codifica y lo decodifica con otro formato, y finalmente lo almacena en un objeto final, despues por medio de open escribiremos el archivo con toda la informacion obtenida previamente y una vez realizado enviaremos por medio de la funcion estado el texto de notificacion de realizado, pasemos a agregar la ultima funcion que nos falta:

def estado(msj):
	_msj_estado.set(msj)
Anuncios

Esta es la funcion encargada de mostrar el mensaje que le enviamos a nuestro cuadro de estado de la ventana, simplemente establece por set el mensaje en esa variable, con esto hemos concluido todo el codigo de este archivo veamos su codigo final antes de probarlo:

guiscrape.py

from tkinter import *
from tkinter import ttk, filedialog
import base64
import json
import os
from bs4 import BeautifulSoup
import requests

config = {}

def buscar_url():
	url = _url.get()
	config['imagenes'] = []
	_imagenes.set(())
	try:
		pagina = requests.get(url)
	except requests.RequestException as err:
		estado(str(err))
	else:
		sopa = BeautifulSoup(pagina.content, 'html.parser')
		imagenes = buscar_imagenes(sopa, url)
		if imagenes:
			_imagenes.set(tuple(img['nombre']
				for img in imagenes))
			estado('Imagenes encontradas: {}'
			.format(len(imagenes)))
		else:
			estado('Imagenes no encontradas')
		config['imagenes'] = imagenes

def buscar_imagenes(sopa, url_base):
	imagenes = []
	for img in sopa.findAll('img'):
		fnt = img.get('src')
		url_img = f'{url_base}/{fnt}'
		nombre = url_img.split('/')[-1]
		imagenes.append(dict(nombre=nombre, url=url_img))
	return imagenes

def guardar():
	if not config.get('imagenes'):
		estado('No hay imagenes para grabar')
		return

	if _metodo_guardar.get() == 'img':
		nombredir = filedialog.askdirectory(mustexist=True)
		guardar_imagenes(nombredir)
	else:
		archivo = filedialog.asksaveasfilename(
			initialfile='imagenes.json',
			filetypes=[('JSON', '.json')])
		guardar_json(archivo)

def guardar_imagenes(nombredir):
	if nombredir and config.get('imagenes'):
		for img in config['imagenes']:
			datos_img = requests.get(img['url']).content
			archivo = os.path.join(nombredir, img['nombre'])
			with open(archivo, 'wb') as f:
				f.write(datos_img)
		estado('Hecho')

def guardar_json(archivo):
	if archivo and config.get('imagenes'):
		datos = {}
		for img in config['imagenes']:
			datos_img = requests.get(img['url']).content
			datos_img_b64 = base64.b64encode(datos_img)
			datos_img_str = datos_img_b64.decode('utf-8')
			datos[img['nombre']] = datos_img_str

		with open(archivo, 'w') as ijson:
			ijson.write(json.dumps(datos))
		estado('Hecho')

def estado(msj):
	_msj_estado.set(msj)

if __name__ == "__main__":
	_raiz = Tk()
	_raiz.title('Aplicacion de Scrape')
	_cuadroPpal = ttk.Frame(_raiz, padding='5 5 5 5')
	_cuadroPpal.grid(row=0, column=0, sticky=(E, W, N, S))
	_cuadro_url = ttk.LabelFrame(
		_cuadroPpal, text='URL', padding='5 5 5 5')
	_cuadro_url.grid(row=0, column=0, sticky=(E, W))
	_cuadro_url.columnconfigure(0, weight=1)
	_cuadro_url.rowconfigure(0, weight=1)
	_url = StringVar()
	_url.set('http://localhost:8000')
	_entrada_url = ttk.Entry(
		_cuadro_url, width=40, textvariable=_url)
	_entrada_url.grid(row=0,column=0,sticky=(E, W, S, N), padx=5)
	_boton_busqueda = ttk.Button(
		_cuadro_url,text='Busqueda de info',command=buscar_url)
	_boton_busqueda.grid(row=0, column=1, sticky=W, padx=5)
	_cuadro_img = ttk.LabelFrame(
		_cuadroPpal, text='Contenido', padding='9 0 0 0')
	_cuadro_img.grid(row=1, column=0, sticky=(N, S, E, W))
	_imagenes = StringVar()
	_listbox_img = Listbox(
		_cuadro_img, listvariable=_imagenes,height=6,width=25)
	_listbox_img.grid(row=0, column=0, sticky=(E,W), pady=5)
	_barraScroll = ttk.Scrollbar(
		_cuadro_img, orient=VERTICAL, command=_listbox_img.yview)
	_barraScroll.grid(row=0,column=1,sticky=(S, N), pady=6)
	_listbox_img.configure(yscrollcommand=_barraScroll.set)
	_cuadro_radio = ttk.Frame(_cuadro_img)
	_cuadro_radio.grid(row=0, column=2, sticky=(N, S, W, E))
	_etq_eleccion = ttk.Label(
		_cuadro_radio, text="Elige como guardar imagenes")
	_etq_eleccion.grid(row=0, column=0, padx=5, pady=5)
	_metodo_guardar = StringVar()
	_metodo_guardar.set('img')
	_img_radio = ttk.Radiobutton(
		_cuadro_radio, text='Como imagenes', 
		variable=_metodo_guardar, value='img')
	_img_radio.grid(
		row=1, column=0, padx=5, pady=2, sticky=W)
	_img_radio.configure(state='normal')
	_json_radio = ttk.Radiobutton(
		_cuadro_radio, text='Como JSON',
		variable=_metodo_guardar, value='json')
	_json_radio.grid(row=2, column=0, padx=5, pady=2, sticky=W)
	_btn_scrapear = ttk.Button(
		_cuadroPpal, text='Scrapealo a todos!', command=guardar)
	_btn_scrapear.grid(row=2, column=0, sticky=E, pady=5)
	_cuadro_estado = ttk.Frame(
		_raiz, relief='sunken', padding='2 2 2 2')
	_cuadro_estado.grid(row=1, column=0, sticky=(E, W, S))
	_msj_estado = StringVar()
	_msj_estado.set('Tipea una URL para comenzar...')
	_estado = ttk.Label(
		_cuadro_estado, textvariable=_msj_estado, anchor=W)
	_estado.grid(row=0, column=0, sticky=(E, W))
	_raiz.mainloop()
Anuncios

Con esto damos por concluido el codigo solo nos resta probarlo para ver como funciona, para ello lo haremos a traves del siguiente video

Anuncios

En el video volvemos a ver como levantar a nuestro servidor a traves de un archivo que generamos en este post, luego chequeamos su funcionamiento para despues probar todas las acciones de nuestro programa, una vez finalizado vemos como hizo todas las tareas solicitadas, por ultimo veamos como quedo finalmente la estructura de nuestro proyecto:

.
├── guiscrape.py
├── scrape.py
└── servidor_simple
    ├── img
    │   ├── tux-alcohol.png
    │   ├── tux-argentina.png
    │   ├── tux-book.png
    │   ├── tux-ebook.png
    │   └── tux-luke.png
    ├── index.html
    └── server.sh
Anuncios

En resumen, hoy hemos terminado la interfaz grafica o GUI para nuestro script, hemos agregado las funciones encargadas de buscar en la pagina, despues la de buscar las imagenes y aislarlas, una vez realizado hemos agregado la opcion de poder guardarlas y hemos visto las dos funciones que nos permiten guardar los archivos o bien en un archivo JSON, espero les haya gustado sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Donación

Es para mantenimento del sitio, gracias!

$1.50