pythonbeautifulsoup

Beautiful soup duplicating link text


I have a function that is meant to extract html to render it in pdf in another function

def setLinks(self, value):
    if isinstance(value, str) and ('<' in value and '>' in value):
        soup = BeautifulSoup(value, 'html.parser')
        paragraphs = []
        links = []

        # Process text and collect links
        for element in soup.descendants:
            if isinstance(element, str) and element.strip():
                paragraphs.append(element.strip())
            elif element.name == 'a' and element.get('href'):
                link_text = element.get_text().strip()
                href = element.get('href')
                links.append((link_text, href))
                if link_text not in paragraphs:
                    paragraphs.append(link_text)
    else:
        if isinstance(value, str):
            paragraphs = value.split('\n')
        else:
            paragraphs = [str(value)]
        links = []
    return links, paragraphs

My input is :

Il faut noter une une similitude de mise en scène avec la<a href="http://www.cappiello.fr/illustrations/"> couverture du "Cri de Paris", n° 201</a>, parue le 2 décembre 1900. Noter l'attitude des deux femmes, l'envolée du noeud de la robe de droite. Le visage de la femme en noir du Cri de Paris est repris pour la femme de gauche. On retrouve la présence d'un meuble sur la gauche pour l'équilibre de la composition.

When I debug, I get :

paragraphs = {list: 4} ['Il faut noter une une similitude de mise en scène avec la', 'couverture du "Cri de Paris", n° 201', 'couverture du "Cri de Paris", n° 201', ", parue le 2 décembre 1900. Noter l'attitude des deux femmes, l'envolée du noeud de la robe de droite. Le visage 
 0 = {str} 'Il faut noter une une similitude de mise en scène avec la'
 1 = {str} 'couverture du "Cri de Paris", n° 201'
 2 = {str} 'couverture du "Cri de Paris", n° 201'
 3 = {str} ", parue le 2 décembre 1900. Noter l'attitude des deux femmes, l'envolée du noeud de la robe de droite. Le visage de la femme en noir du Cri de Paris est repris pour la femme de gauche. On retrouve la présence d'un meuble sur la gauche pour l'équilibre de  

Why soup.descendants is looping first on the link :

<a href="http://www.cappiello.fr/illustrations/"> couverture du "Cri de Paris", n° 201</a>

and then on the text couverture du "Cri de Paris", n° 201 ???


Solution

  • for element in soup.descendants:
    

    means that you will iterate through all elements recursively. And text between brackets is children of "a" element, so it gets your paragraph twice. If you want to avoid this behavior, you could try to use

    for element in soup.children:
    

    instead