python - how - Beautiful Soup-Encontrar el primer enlace en un artículo
python beautifulsoup findall (1)
Estoy creando una solución de Python para este problema, pero estoy teniendo problemas para superar algunos casos extremos.
El problema con el que me estoy metiendo surge para una página como esta, donde este enlace es el que debería extraerse, ya que es el primero fuera del paréntesis. Por el contrario, algunos artículos son como este donde el enlace aparece antes del primer paréntesis.
La manera en que estoy manejando estos casos actualmente es iterando inicialmente a través de los elementos y el texto en la etiqueta del primer párrafo (versión codificada) y verificando cuál se encuentra primero entre ''('' y <a>
. Si <a>
se encuentra primero (es decir, antes de que se haya alcanzado un paréntesis), simplemente tomo ese enlace. Si primero se encuentra un paréntesis, espero hasta que los paréntesis estén cerrados y luego tomo el siguiente ''
En efecto, estoy obteniendo el hijo directo del elemento del primer párrafo que podría hacerse con algo como:
soup = BeautifulSoup(response.content, "lxml")
soup.select_one("#mw-content-text > p > a")
Lo que creo que funcionaría aquí es usar dicha instrucción select para encontrar el primer enlace en el prefijo desde el comienzo de th <p>
hasta el primer paréntesis o (si no hay un enlace en el prefijo) buscar el enlace inmediatamente siguiendo el paréntesis de cierre usando algo similar a lo que estoy haciendo actualmente:
`findNext(''a'').attrs[''href'']`
Si se va a utilizar dicho enfoque, surgirán múltiples problemas, que incluyen: 1. Cómo obtener el prefijo hasta el primer paréntesis con solo los elementos secundarios directos del ''
¿Hay una manera simplificada de hacer esto? Si hay un mejor enfoque, ¿cuál sería?
Este problema me recuerda el algoritmo popular y el problema de las estructuras de datos cuando necesita verificar si los paréntesis u otros corchetes están equilibrados. Para este tipo de problemas, es conveniente usar una estructura de datos de pila .
Entonces, en este caso, presionaremos para apilar si hay un paréntesis de apertura y saldrá de él si hay uno de cierre . El enlace válido para nosotros sería uno cuando la pila está vacía :
import requests
from bs4 import BeautifulSoup, NavigableString, Tag
urls = [
"https://en.wikipedia.org/wiki/Modern_Greek",
"https://en.wikipedia.org/wiki/Diglossia"
]
with requests.Session() as session:
for url in urls:
response = session.get(url)
soup = BeautifulSoup(response.content, "html.parser")
stack = []
for child in soup.select_one("#mw-content-text > p").children:
if isinstance(child, NavigableString):
if "(" in child:
stack.append("(")
if ")" in child:
stack.pop()
if isinstance(child, Tag) and child.name == "a" and not stack:
print(child.get_text())
break
Imprime dialects
para la página "Griega moderna" y la linguistics
para "Diglossia". Ambos casos son manejados.