Proyecto: Generador de Códigos QR con Python - Tutorial Completo

👤 Admin 📅 24 de octubre, 2025 ⏱ 16 min 🏷 Proyectos Python

¿Qué son los Códigos QR?

Los códigos QR (Quick Response) son códigos de barras bidimensionales que pueden almacenar información como URLs, texto, contactos, credenciales WiFi y más. Son ampliamente usados para compartir información de forma rápida y eficiente.

Instalación de Bibliotecas

# Instalar bibliotecas necesarias
pip install qrcode
pip install pillow  # Para procesamiento de imágenes
pip install qrcode[pil]  # Versión con PIL integrado

Generador Básico de QR

import qrcode

# Crear código QR simple
data = "https://www.ejemplo.com"

# Generar QR
qr = qrcode.make(data)

# Guardar imagen
qr.save("mi_qr.png")

print("Código QR generado exitosamente!")

Generador con Configuración Personalizada

import qrcode
from qrcode.image.styledpil import StyledPilImage
from qrcode.image.styles.moduledrawers import RoundedModuleDrawer

def generar_qr_personalizado(data, nombre_archivo="qr_code.png"):
    """
    Generar código QR con configuración personalizada
    """
    # Crear objeto QRCode
    qr = qrcode.QRCode(
        version=1,  # Tamaño del QR (1-40, None para automático)
        error_correction=qrcode.constants.ERROR_CORRECT_H,  # Nivel de corrección de errores
        box_size=10,  # Tamaño de cada cuadro
        border=4,  # Grosor del borde
    )
    
    # Agregar datos
    qr.add_data(data)
    qr.make(fit=True)
    
    # Crear imagen
    img = qr.make_image(
        fill_color="black",
        back_color="white"
    )
    
    # Guardar
    img.save(nombre_archivo)
    print(f"QR guardado como: {nombre_archivo}")
    return img

# Usar función
generar_qr_personalizado(
    "https://www.byteninja.com",
    "byteninja_qr.png"
)

Generador con Colores Personalizados

import qrcode

def qr_con_colores(data, color_qr="blue", color_fondo="yellow"):
    """
    Generar QR con colores personalizados
    """
    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=10,
        border=4,
    )
    
    qr.add_data(data)
    qr.make(fit=True)
    
    img = qr.make_image(
        fill_color=color_qr,
        back_color=color_fondo
    )
    
    nombre_archivo = f"qr_{color_qr}_{color_fondo}.png"
    img.save(nombre_archivo)
    print(f"QR con colores guardado: {nombre_archivo}")
    return img

# Diferentes combinaciones de colores
qr_con_colores("https://ejemplo.com", "darkblue", "lightblue")
qr_con_colores("https://ejemplo.com", "darkgreen", "lightgreen")
qr_con_colores("https://ejemplo.com", "purple", "pink")

Tipos de Datos para QR

1. URL

def generar_qr_url(url):
    qr = qrcode.make(url)
    qr.save("qr_url.png")
    return qr

# Usar
generar_qr_url("https://www.google.com")

2. Texto Simple

def generar_qr_texto(texto):
    qr = qrcode.make(texto)
    qr.save("qr_texto.png")
    return qr

# Usar
generar_qr_texto("Este es un mensaje secreto en código QR!")

3. vCard (Tarjeta de Contacto)

def generar_qr_vcard(nombre, telefono, email, organizacion="", sitio_web=""):
    """
    Generar QR con información de contacto vCard
    """
    vcard = f"""
BEGIN:VCARD
VERSION:3.0
FN:{nombre}
TEL:{telefono}
EMAIL:{email}
ORG:{organizacion}
URL:{sitio_web}
END:VCARD
    """.strip()
    
    qr = qrcode.make(vcard)
    qr.save("qr_contacto.png")
    print("QR de contacto generado")
    return qr

# Usar
generar_qr_vcard(
    nombre="Juan Pérez",
    telefono="+57 300 1234567",
    email="juan@ejemplo.com",
    organizacion="ByteNinja",
    sitio_web="https://www.byteninja.com"
)

4. Credenciales WiFi

def generar_qr_wifi(ssid, password, seguridad="WPA", oculta=False):
    """
    Generar QR para conectarse a WiFi automáticamente
    
    Args:
        ssid: Nombre de la red
        password: Contraseña
        seguridad: WPA, WEP, o nopass
        oculta: True si la red está oculta
    """
    hidden = "true" if oculta else "false"
    
    wifi_string = f"WIFI:T:{seguridad};S:{ssid};P:{password};H:{hidden};"
    
    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=10,
        border=4,
    )
    qr.add_data(wifi_string)
    qr.make(fit=True)
    
    img = qr.make_image(fill_color="blue", back_color="white")
    img.save("qr_wifi.png")
    print(f"QR WiFi generado para red: {ssid}")
    return img

# Usar
generar_qr_wifi(
    ssid="MiRedWiFi",
    password="miPassword123",
    seguridad="WPA"
)

5. Email

def generar_qr_email(destinatario, asunto="", cuerpo=""):
    """
    Generar QR para enviar email
    """
    email_string = f"mailto:{destinatario}?subject={asunto}&body={cuerpo}"
    
    qr = qrcode.make(email_string)
    qr.save("qr_email.png")
    print(f"QR email generado para: {destinatario}")
    return qr

# Usar
generar_qr_email(
    destinatario="contacto@ejemplo.com",
    asunto="Consulta desde QR",
    cuerpo="Hola, encontré tu código QR..."
)

6. SMS

def generar_qr_sms(numero, mensaje=""):
    """
    Generar QR para enviar SMS
    """
    sms_string = f"SMSTO:{numero}:{mensaje}"
    
    qr = qrcode.make(sms_string)
    qr.save("qr_sms.png")
    print(f"QR SMS generado para: {numero}")
    return qr

# Usar
generar_qr_sms(
    numero="+573001234567",
    mensaje="Hola desde código QR!"
)

7. Geolocalización

def generar_qr_ubicacion(latitud, longitud, nombre_lugar=""):
    """
    Generar QR con coordenadas geográficas
    """
    geo_string = f"geo:{latitud},{longitud}?q={latitud},{longitud}({nombre_lugar})"
    
    qr = qrcode.make(geo_string)
    qr.save("qr_ubicacion.png")
    print(f"QR ubicación generado: {nombre_lugar}")
    return qr

# Usar (ejemplo: Torre Eiffel)
generar_qr_ubicacion(
    latitud=48.858370,
    longitud=2.294481,
    nombre_lugar="Torre Eiffel"
)

Generador de QR con Logo

from PIL import Image
import qrcode

def generar_qr_con_logo(data, ruta_logo, nombre_archivo="qr_con_logo.png"):
    """
    Generar código QR con logo en el centro
    """
    # Crear QR con alta corrección de errores
    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_H,  # Alta corrección
        box_size=10,
        border=4,
    )
    
    qr.add_data(data)
    qr.make(fit=True)
    
    # Crear imagen QR
    img_qr = qr.make_image(fill_color="black", back_color="white").convert('RGB')
    
    # Abrir logo
    logo = Image.open(ruta_logo)
    
    # Calcular tamaño del logo (10% del QR)
    qr_width, qr_height = img_qr.size
    logo_size = qr_width // 5
    
    # Redimensionar logo
    logo = logo.resize((logo_size, logo_size), Image.LANCZOS)
    
    # Calcular posición central
    logo_pos = ((qr_width - logo_size) // 2, (qr_height - logo_size) // 2)
    
    # Pegar logo en el centro
    img_qr.paste(logo, logo_pos)
    
    # Guardar
    img_qr.save(nombre_archivo)
    print(f"QR con logo guardado: {nombre_archivo}")
    return img_qr

# Usar
# generar_qr_con_logo(
#     "https://www.byteninja.com",
#     "logo.png",
#     "qr_byteninja_logo.png"
# )

Clase Generadora Completa

import qrcode
from PIL import Image
import os

class GeneradorQR:
    def __init__(self, carpeta_salida="qr_codes"):
        self.carpeta_salida = carpeta_salida
        
        # Crear carpeta si no existe
        if not os.path.exists(carpeta_salida):
            os.makedirs(carpeta_salida)
    
    def generar(self, data, nombre_archivo="qr.png", 
                version=1, box_size=10, border=4,
                fill_color="black", back_color="white"):
        """
        Método genérico para generar QR
        """
        qr = qrcode.QRCode(
            version=version,
            error_correction=qrcode.constants.ERROR_CORRECT_H,
            box_size=box_size,
            border=border,
        )
        
        qr.add_data(data)
        qr.make(fit=True)
        
        img = qr.make_image(fill_color=fill_color, back_color=back_color)
        
        ruta_completa = os.path.join(self.carpeta_salida, nombre_archivo)
        img.save(ruta_completa)
        
        print(f"✅ QR guardado: {ruta_completa}")
        return img
    
    def generar_url(self, url, nombre_archivo="qr_url.png"):
        return self.generar(url, nombre_archivo)
    
    def generar_texto(self, texto, nombre_archivo="qr_texto.png"):
        return self.generar(texto, nombre_archivo)
    
    def generar_vcard(self, nombre, telefono, email, 
                      organizacion="", sitio_web="",
                      nombre_archivo="qr_contacto.png"):
        vcard = f"""
BEGIN:VCARD
VERSION:3.0
FN:{nombre}
TEL:{telefono}
EMAIL:{email}
ORG:{organizacion}
URL:{sitio_web}
END:VCARD""".strip()
        return self.generar(vcard, nombre_archivo)
    
    def generar_wifi(self, ssid, password, seguridad="WPA",
                     nombre_archivo="qr_wifi.png"):
        wifi_string = f"WIFI:T:{seguridad};S:{ssid};P:{password};;"
        return self.generar(wifi_string, nombre_archivo, 
                          fill_color="blue", back_color="lightblue")
    
    def generar_lote(self, lista_datos, prefijo="qr"):
        """
        Generar múltiples códigos QR
        """
        for i, data in enumerate(lista_datos, 1):
            nombre = f"{prefijo}_{i}.png"
            self.generar(data, nombre)
        
        print(f"\n✅ {len(lista_datos)} códigos QR generados")
    
    def con_logo(self, data, ruta_logo, nombre_archivo="qr_logo.png"):
        """
        Generar QR con logo
        """
        qr = qrcode.QRCode(
            version=1,
            error_correction=qrcode.constants.ERROR_CORRECT_H,
            box_size=10,
            border=4,
        )
        
        qr.add_data(data)
        qr.make(fit=True)
        
        img_qr = qr.make_image(fill_color="black", back_color="white").convert('RGB')
        
        try:
            logo = Image.open(ruta_logo)
            
            qr_width, qr_height = img_qr.size
            logo_size = qr_width // 5
            logo = logo.resize((logo_size, logo_size), Image.LANCZOS)
            
            logo_pos = ((qr_width - logo_size) // 2, (qr_height - logo_size) // 2)
            img_qr.paste(logo, logo_pos)
        
        except Exception as e:
            print(f"⚠️ Error agregando logo: {e}")
        
        ruta_completa = os.path.join(self.carpeta_salida, nombre_archivo)
        img_qr.save(ruta_completa)
        print(f"✅ QR con logo guardado: {ruta_completa}")
        return img_qr

# ===== USAR LA CLASE =====

if __name__ == "__main__":
    # Crear instancia
    generador = GeneradorQR(carpeta_salida="mis_qr_codes")
    
    # Generar diferentes tipos
    generador.generar_url("https://www.byteninja.com")
    generador.generar_texto("¡Hola desde ByteNinja!")
    
    generador.generar_vcard(
        nombre="Juan Pérez",
        telefono="+573001234567",
        email="juan@byteninja.com",
        organizacion="ByteNinja",
        sitio_web="https://www.byteninja.com"
    )
    
    generador.generar_wifi(
        ssid="ByteNinjaWiFi",
        password="SuperSecure123"
    )
    
    # Generar lote
    urls = [
        "https://www.google.com",
        "https://www.github.com",
        "https://www.stackoverflow.com"
    ]
    generador.generar_lote(urls, prefijo="sitio")
    
    print("\n🎉 Todos los códigos QR generados exitosamente!")

Interfaz Gráfica con Tkinter

import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import qrcode
from PIL import Image, ImageTk
import os

class GeneradorQRGUI:
    def __init__(self, ventana):
        self.ventana = ventana
        self.ventana.title("Generador de Códigos QR")
        self.ventana.geometry("600x700")
        
        self.crear_interfaz()
    
    def crear_interfaz(self):
        # Frame principal
        main_frame = ttk.Frame(self.ventana, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # Título
        titulo = ttk.Label(main_frame, text="Generador de Códigos QR", 
                          font=("Arial", 16, "bold"))
        titulo.grid(row=0, column=0, columnspan=2, pady=10)
        
        # Tipo de QR
        ttk.Label(main_frame, text="Tipo de QR:").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.tipo_qr = ttk.Combobox(main_frame, 
                                    values=["URL", "Texto", "WiFi", "Contacto"],
                                    state="readonly", width=40)
        self.tipo_qr.set("URL")
        self.tipo_qr.grid(row=1, column=1, pady=5)
        
        # Input de datos
        ttk.Label(main_frame, text="Datos:").grid(row=2, column=0, sticky=tk.W, pady=5)
        self.entrada_datos = tk.Text(main_frame, height=5, width=45)
        self.entrada_datos.grid(row=2, column=1, pady=5)
        
        # Colores
        ttk.Label(main_frame, text="Color QR:").grid(row=3, column=0, sticky=tk.W, pady=5)
        self.color_qr = ttk.Entry(main_frame, width=42)
        self.color_qr.insert(0, "black")
        self.color_qr.grid(row=3, column=1, pady=5)
        
        ttk.Label(main_frame, text="Color Fondo:").grid(row=4, column=0, sticky=tk.W, pady=5)
        self.color_fondo = ttk.Entry(main_frame, width=42)
        self.color_fondo.insert(0, "white")
        self.color_fondo.grid(row=4, column=1, pady=5)
        
        # Botón generar
        btn_generar = ttk.Button(main_frame, text="Generar QR", 
                                command=self.generar_qr)
        btn_generar.grid(row=5, column=0, columnspan=2, pady=20)
        
        # Canvas para mostrar QR
        self.canvas = tk.Canvas(main_frame, width=400, height=400, bg="white")
        self.canvas.grid(row=6, column=0, columnspan=2, pady=10)
        
        # Botón guardar
        btn_guardar = ttk.Button(main_frame, text="Guardar QR", 
                                command=self.guardar_qr)
        btn_guardar.grid(row=7, column=0, columnspan=2, pady=10)
        
        self.imagen_qr = None
    
    def generar_qr(self):
        datos = self.entrada_datos.get("1.0", tk.END).strip()
        
        if not datos:
            messagebox.showwarning("Advertencia", "Ingresa datos para el QR")
            return
        
        try:
            qr = qrcode.QRCode(
                version=1,
                error_correction=qrcode.constants.ERROR_CORRECT_H,
                box_size=10,
                border=4,
            )
            
            qr.add_data(datos)
            qr.make(fit=True)
            
            self.imagen_qr = qr.make_image(
                fill_color=self.color_qr.get(),
                back_color=self.color_fondo.get()
            )
            
            # Mostrar en canvas
            self.imagen_qr = self.imagen_qr.resize((350, 350), Image.LANCZOS)
            self.photo = ImageTk.PhotoImage(self.imagen_qr)
            
            self.canvas.delete("all")
            self.canvas.create_image(200, 200, image=self.photo)
            
            messagebox.showinfo("Éxito", "QR generado exitosamente!")
        
        except Exception as e:
            messagebox.showerror("Error", f"Error generando QR: {e}")
    
    def guardar_qr(self):
        if self.imagen_qr is None:
            messagebox.showwarning("Advertencia", "Primero genera un QR")
            return
        
        archivo = filedialog.asksaveasfilename(
            defaultextension=".png",
            filetypes=[("PNG", "*.png"), ("Todos", "*.*")]
        )
        
        if archivo:
            self.imagen_qr.save(archivo)
            messagebox.showinfo("Éxito", f"QR guardado: {archivo}")

if __name__ == "__main__":
    ventana = tk.Tk()
    app = GeneradorQRGUI(ventana)
    ventana.mainloop()

Script de Línea de Comandos

# qr_cli.py
import argparse
import qrcode

def main():
    parser = argparse.ArgumentParser(description='Generador de Códigos QR')
    parser.add_argument('data', help='Datos para el código QR')
    parser.add_argument('-o', '--output', default='qr.png', help='Archivo de salida')
    parser.add_argument('-c', '--color', default='black', help='Color del QR')
    parser.add_argument('-b', '--background', default='white', help='Color de fondo')
    parser.add_argument('-s', '--size', type=int, default=10, help='Tamaño de caja')
    
    args = parser.parse_args()
    
    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_H,
        box_size=args.size,
        border=4,
    )
    
    qr.add_data(args.data)
    qr.make(fit=True)
    
    img = qr.make_image(fill_color=args.color, back_color=args.background)
    img.save(args.output)
    
    print(f"✅ QR guardado: {args.output}")

if __name__ == '__main__':
    main()
# Usar desde terminal
python qr_cli.py "https://www.ejemplo.com" -o sitio.png
python qr_cli.py "Texto de prueba" -c blue -b yellow -o texto.png

Buenas Prácticas

  • Corrección de errores alta: Usa ERROR_CORRECT_H para QR con logos
  • Tamaño apropiado: Ajusta box_size según el uso
  • Contraste: Usa colores con buen contraste
  • Testing: Prueba los QR antes de distribuir
  • Formato PNG: Mejor calidad que JPEG para QR
  • Documentación: Indica qué contiene cada QR

Conclusión

Generar códigos QR con Python es simple y versátil. Puedes crear QR para URLs, texto, WiFi, contactos y mucho más con solo unas líneas de código. La biblioteca qrcode hace que sea fácil personalizar colores, tamaños y agregar logos para crear códigos QR profesionales y atractivos.