Canibal-SEO / app.py
tx3bas's picture
Update app.py
469008d verified
import gradio as gr
import requests
from bs4 import BeautifulSoup
import re
from urllib.parse import urlparse
def buscar_google(query, dominio, hl='es', num_results=100):
all_results = []
posiciones_dominio = []
posiciones_dominio_exacto = []
url_objetivo = dominio
dominio_objetivo = urlparse(url_objetivo).netloc
table_html = "<summary>Ver Resultados</summary><table border='1'><tr><th>Posici贸n</th><th>T铆tulo</th><th>URL</th></tr>"
estilo = "color: #ed4b4b;"
for start in range(0, num_results, 10):
url = f"https://www.google.com/search?q={query}&hl={hl}&start={start}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.3"
}
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
search_results = soup.find_all('div', attrs={'class': 'tF2Cxc'})
all_results.extend(search_results)
for i, result in enumerate(all_results[:num_results]):
header = result.find('h3')
header = header.text if header else "Sin t铆tulo"
link = result.find('a', href=True)['href']
link_clean = re.search("(?P<url>https?://[^\s]+)", link).group("url")
dominio_resultado = urlparse(link_clean).netloc
estilo_dominio = ""
if dominio_objetivo in dominio_resultado:
posiciones_dominio.append(i + 1)
if link_clean == url_objetivo:
posiciones_dominio_exacto.append(i + 1)
estilo_dominio = estilo
else:
estilo_dominio = estilo # Marcar en rojo las URLs del mismo dominio
table_html += f"<tr><td>{i+1}</td><td>{header}</td><td><span><a href='{link_clean}' title='{link_clean}' style='{estilo_dominio}'>{link_clean}</a></span></td></tr>"
table_html += "</table>"
# Construcci贸n del mensaje y la tabla HTML
mensaje = ""
emoji = ""
if posiciones_dominio:
first_position = posiciones_dominio[0]
if first_position == 1:
emoji = f"{posiciones_dominio} 馃"
elif first_position <= 3:
emoji = f"{posiciones_dominio} 馃槑"
elif first_position <= 5:
emoji = f"{posiciones_dominio} 馃槅"
elif first_position <= 10:
emoji = f"{posiciones_dominio} 馃檪"
elif first_position <= 100:
emoji = f"{posiciones_dominio} 馃槓"
else:
emoji = f"No est谩 en el top 100 馃槶"
if len(posiciones_dominio) > 1 and 1 in posiciones_dominio:
mensaje = f"Parasitaci贸n SEO: {url_objetivo} se encuentra en las posiciones {posiciones_dominio}"
elif len(posiciones_dominio) > 1:
mensaje = f"Canibalizaci贸n: {url_objetivo} se encuentra en las posiciones {posiciones_dominio}"
elif len(posiciones_dominio) == 1 and len(posiciones_dominio_exacto) == 0:
mensaje = f"Canibalizaci贸n: URL diferente del dominio en la posici贸n {posiciones_dominio[0]}"
elif len(posiciones_dominio) == 1:
mensaje = f"Sin canibalizaci贸n: {url_objetivo} se encuentra en la posici贸n {posiciones_dominio[0]}"
else:
mensaje = f"{url_objetivo} no se encuentra en el top 100"
mensaje_completo = f"Posici贸n: {emoji}<br>{mensaje}"
html_output = f"<div><b>{mensaje_completo}</b></div>"
html_output += "<details style='padding: 10px; background: #f3f3f3; border: solid 0; border-radius: 8px; margin-top: 10px;'>"
html_output += table_html
html_output += "</details>"
return html_output
def canibalizacion_interface(url, keyword):
# Comprobar si la URL cumple con el patr贸n http o https
if not re.match(r'^https?://', url):
return "<p>Error: Introduce una URL con el protocolo http o https.</p>"
return buscar_google(keyword, url)
iface = gr.Interface(
fn=canibalizacion_interface,
inputs=["text", "text"],
outputs="html",
title="<div style='margin:0 auto;text-align:center'><div style='margin:0 auto;text-align:center'><img style='width:100px;display: inline-table;margin-bottom:-10px' src='https://artxeweb.com/media/files/canibal.jpg'><p>Canibal SEO</p></div>",
description="<p style='margin-bottom:10px;text-align:center;background: #ffffff; padding: 8px; border-radius: 8px; border-width: 1px; border: solid 1px #e5e7eb;'>Encuentra posibles canibalizaciones y parasitaciones en Google a partir de una URL y una palabra clave.</p>",
article="<div style='margin-top:10px'><p style='text-align: center !important; background: #ffffff; padding: 5px 30px; border-radius: 8px; border-width: 1px; border: solid 1px #e5e7eb; width: fit-content; margin: auto;'>Desarrollada por <a style='text-decoration: none !important; color: #e12a31 !important;' href='https://artxeweb.com/'>漏 Artxe Web</a></p></div>"
)
iface.launch()