Estoy haciendo un pequeño proyecto en el que extraigo las apariciones de líderes políticos en los periódicos. Algunas veces se mencionará a un político, y no hay un padre o un niño con un enlace. (Debido a que supongo que es un marcado semánticamente malo).Encontrar el enlace más cercano con BeautifullSoup (python)
Así que quiero crear una función que pueda encontrar el enlace más cercano y luego extraerlo. En el caso debajo de la cadena de búsqueda es Rasmussen
y el enlace que quiero es: /307046
.
#-*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import re
tekst = '''
<li>
<div class="views-field-field-webrubrik-value">
<h3>
<a href="/307046">Claus Hjort spiller med mrkede kort</a>
</h3>
</div>
<div class="views-field-field-skribent-uid">
<div class="byline">Af: <span class="authors">Dennis Kristensen</span></div>
</div>
<div class="views-field-field-webteaser-value">
<div class="webteaser">Claus Hjort Frederiksens argumenter for at afvise
trepartsforhandlinger har ikke hold i virkeligheden. Hans rinde er nok
snarere at forberede det ideologiske grundlag for en Løkke Rasmussens
genkomst som statsministe
</div>
</div>
<span class="views-field-view-node">
<span class="actions">
<a href="/307046">Ls mere</a>
|
<a href="/307046/#comments">Kommentarer (4)</a>
</span>
</span>
</li>
'''
to_find = "Rasmussen"
soup = BeautifulSoup(tekst)
contexts = soup.find_all(text=re.compile(to_find))
def find_nearest(element, url, direction="both"):
"""Find the nearest link, relative to a text string.
When complete it will search up and down (parent, child),
and only X levels up down. These features are not implemented yet.
Will then return the link the fewest steps away from the
original element. Assumes we have already found an element"""
# Is the nearest link readily available?
# If so - this works and extracts the link.
if element.find_parents('a'):
for artikel_link in element.find_parents('a'):
link = artikel_link.get('href')
# sometimes the link is a relative link - sometimes it is not
if ("http" or "www") not in link:
link = url+link
return link
# But if the link is not readily available, we will go up
# This is (I think) where it goes wrong
# ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
if not element.find_parents('a'):
element = element.parent
# Print for debugging
print element #on the 2nd run (i.e <li> this finds <a href=/307056>
# So shouldn't it be caught as readily available above?
print u"Found: %s" % element.name
# the recursive call
find_nearest(element,url)
# run it
if contexts:
for a in contexts:
find_nearest(element=a, url="http://information.dk")
La llamada directa a continuación funciona:
print contexts[0].parent.parent.parent.a['href'].encode('utf-8')
Como referencia todo el código siento está en bitbucket: https://bitbucket.org/achristoffersen/politikere-i-medierne
(EP Utilizar BeautifullSoup 4)
EDITAR: SimonSapin me pide que defina ne arest: Por "más cercano" me refiero al enlace que tiene el menor número de niveles de anidación fuera del término de búsqueda, en cualquier dirección. En el texto anterior, el a href
producido por el sitio de periódico basado en drupal, no es un padre directo o hijo de la etiqueta donde se encuentra la cadena de búsqueda. Así que BeautifullSoup no puede encontrarlo.
Sospecho que un "menor número de charachters" de distancia a menudo también funcionaría. En ese caso, una mezcla podría ser pirateada junto con el hallazgo y la confusión, pero realmente me gustaría hacerlo a través de BS. Como esto funcionaría: contexts[0].parent.parent.parent.a['href'].encode('utf-8')
, debe ser posible generalizarlo a un script.
EDIT: Tal vez debería hacer hincapié en que estoy buscando una solución BeautifulSoup. La combinación de BS con una búsqueda de respiración personalizada/simpel según lo sugerido por @ erik85 se convertiría rápidamente en un desastre, creo.
¿Cómo se define "cerca", y cuál es tu pregunta? –
@SimonSapin Pregunta actualizada. Gracias. – Andreas
Y mi pregunta es: ¿cómo extraigo esta lin/cuál es incorrecto con mi código. Gracias – Andreas