Une partie d'un html est structurée comme ci-dessous. Je veux en obtenir le "titre" et le "temps". Je peux les obtenir séparément, comme:

from bs4 import BeautifulSoup


pages = '<div class="content"> \
                <a href="Org"> \
                        <h3 class="title"> \
                            Dep. Manager</h3> \
                        </a> \
                <div class="contributor"></div> \
                <p>John</p> \
                <time class="time"> \
                        <span class="timestamp">May 02 2016</span> \
                    </time> \
                </div>'


soup = BeautifulSoup(pages, "lxml")


soup.prettify()


s = soup.find_all(class_ = "title")[0]

t = soup.find_all('span', class_ = "timestamp")[0].text.strip()


pp_title = s.text.strip()

print t

print (pp_title)

Il me rend ce que je voulais.

Dep. Manager
May 02 2016

Pour le "temps", je veux une autre façon de l'obtenir, car le "temps" est toujours en dessous du "titre". J'ai essayé cette ligne pour avoir le "temps", ça ne marche pas.

print (s.parent.next_sibling.next_sibling)

Quelle est la bonne façon d'obtenir le «temps» de la relation au «titre»? Merci.

1
Mark K 3 nov. 2019 à 13:56

4 réponses

Meilleure réponse

Vous pouvez findParent en spécifiant les détails:

t = s.findParent("div", class_='content').find('span', class_='timestamp').text.strip()

Exemple:

titles = soup.find_all(class_="title")
for title in titles:
    timestamp = title.findParent("div", class_='content').find('span', class_='timestamp').text.strip()
    print(title.text.strip(), timestamp)
2
Sers 3 nov. 2019 à 11:11

Je ne sais pas si le problème réside dans la chaîne que vous fournissez ou ailleurs, mais chaque autre appel à next_sibling renvoie u' '. J'ai donc essayé ceci:

s.parent.next_sibling.next_sibling.next_sibling.next_sibling.next_sibling.next_sibling.findChildren()[0]

Je sais que c'est long, mais ça fait le travail.

1
Maxxik CZ 3 nov. 2019 à 11:19

Sélectionnez le parent partagé, puis saisissez les enfants par classe. Suppose que le parent a toujours les deux. Vous pouvez modifier le sélecteur pour vous assurer qu'il possède les deux si nécessaire.

from bs4 import BeautifulSoup as bs

html = '''
<div class="content"> \
    <a href="Org"> \
                        <h3 class="title"> \
                            Dep. Manager</h3> \
                        </a> \
    <div class="contributor"></div> \
    <p>John</p> \
    <time class="time"> \
        <span class="timestamp">May 02 2016</span> \
    </time> \
</div>
'''
soup = bs(html, 'lxml')
items = [i.text.strip() for i in soup.select('.content:has(.title) .title, .content:has(.title) .timestamp')]
print(items)
1
QHarr 3 nov. 2019 à 14:24

Vous pouvez utiliser soup.find_all avec re:

import re
from bs4 import BeautifulSoup as soup
result = [i.get_text(strip=True) for i in soup(pages, 'html.parser').find_all(re.compile('h3|span'), {'class':re.compile('title|timestamp')})]

Production:

['Dep. Manager', 'May 02 2016']
1
Ajax1234 3 nov. 2019 à 14:16