Python BeautifulSoup, чтобы получить контент от родителя / родного брата - PullRequest
1 голос
/ 03 ноября 2019

Часть HTML структурирована, как показано ниже. Я хочу получить от нее «звание» и «время». Я могу получить их отдельно, например:

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)

Он возвращает мне то, что хотел.

Dep. Manager
May 02 2016

Для «времени» я хочу получить другой способ, как «время»Всегда ниже «заголовка». Я попробовал эту строку, чтобы получить «время», оно не работает.

print (s.parent.next_sibling.next_sibling)

Как правильно получить «время» из отношения к «названию»? спасибо.

Ответы [ 4 ]

2 голосов
/ 03 ноября 2019

Вы можете findParent с указанием деталей:

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

Пример:

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)
1 голос
/ 03 ноября 2019

Выберите для общего родителя, затем выберите детей по классу. Предполагается, что родитель всегда имеет оба. Вы можете изменить селектор, чтобы обеспечить оба при необходимости.

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 голос
/ 03 ноября 2019

Вы можете использовать soup.find_all с 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')})]

Выход:

['Dep. Manager', 'May 02 2016']
1 голос
/ 03 ноября 2019

Я не знаю, кроется ли проблема в строке, которую вы предоставляете, или где-то еще, но каждый следующий вызов next_sibling возвращает u' '. Итак, я попробовал это:

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

Я знаю, что это долго, но он выполняет свою работу.

...