#python #beautifulsoup
#python #beautifulsoup
Вопрос:
Можно ли перемещаться из текущей позиции в DOM вверх и вниз, когда общим идентификатором является только текст?
<div>changing text</div>
<div>fixed text</div>
Как получить текст changing text
при поиске fixed text
и переходе к родительскому div?
Что я пробовал:
x = soup.body.findAll(text=re.compile('fixed text')).parent
AttributeError: 'ResultSet' object has no attribute 'parent'
Комментарии:
1. Что произошло с вашей попыткой?
2. Я получаю сообщение об ошибке: AttributeError: у объекта ‘ResultSet’ нет атрибута ‘parent’ …. извините, я добавлю его к вопросу
3.
findAll
возвращаетResultSet
— список элементов. Вы хотите выполнить операцию с элементами внутри результирующего набора.4. @BitByBit проверьте мой отредактированный ответ
5. @ TalesPadua Это не работает, потому что, даже если они все еще только братья и сестры, вам все равно придется сначала перейти к родителям. Я не знаю почему!
Ответ №1:
Эта программа может делать то, что вы хотите:
from bs4 import BeautifulSoup
import re
html = '<body><div>changing text</div><div>fixed text</div><body>'
soup = BeautifulSoup(html)
x = soup.body.findAll(text=re.compile('fixed text'))[0].parent.previous_sibling
assert x.text == 'changing text'
Комментарии:
1. Мне нравится, но, учитывая это
find_all
, понимание списка может быть в порядкеdivs = [elem.previous_sibling for elem in soup.body.findAll(text=re.compile('fixed text'))]
2. Это работает, но я не совсем понимаю. Как упоминал Tales, на самом деле это братья и сестры, так почему мы привлекаем сюда родителей?
3. @BitByBit — это не должно работать, если они являются братьями и сестрами. Но у нас недостаточно вашего документа, чтобы разобраться в этом. Я опубликовал пример для составления списка divs … это работает?
4.
.parent
требуется, потомуfindAll
что возвращает строковый узел, а не<div>
узел. Если вы хотитеfindAll
вернуть<div>
узел, попробуйте:x = soup.body.findAll('div', text=re.compile('fixed text'))[0].previous_sibling
5. @tdelaney Вы были близки, Роб прав.
divs = [elem.parent.previous_sibling for elem in soup.body.findAll(text=re.compile('fixed text'))]
Ответ №2:
Ошибка, с которой вы сталкиваетесь, связана с вызовом parent
результирующего набора, списка результатов. Если вам нужно получить несколько результатов, попробуйте:
x = soup.body.find_all(text=re.compile('fixed text'))
for i in x:
previous_div = i.previous_sibling
Если вы не хотите находить несколько результатов, просто измените find_all на find:
x = soup.body.find(text=re.compile('fixed text')).previous_sibling
Обратите внимание, что я заменяю parent на previous_sibling, поскольку divs находятся на одном уровне
Комментарии:
1. Вы изменили это, чтобы найти только один элемент. OP использует
findAll
и, предположительно, хочет выполнить обработку на нескольких узлах.2. Да, но ошибка, с которой сталкивается OP, связана с использованием parent в результирующем наборе. Я отредактирую, чтобы уточнить