Как найти имя тега по тексту в BeautifulSoup - PullRequest
1 голос
/ 01 августа 2020

У меня есть следующий код html:

soup = BeautifulSoup("<div class='mydiv'><p style='xyz'>123</p><p>456</p><p style='xyz'>789</p><p>abc</p></div>", 'lxml')

Теперь у меня есть текст '456'.

Я хочу найти текст во всех тегах, которые имеют то же имя тега, содержащее текст '456'.

То есть в html, <p>456</p> содержит 456, тогда мы должны найти abc из-за <p>abc</p>, но не 123 и 789, потому что <p style> в <p style='xyz'>123</p> и <p style='xyz'>789</p>.

Обратите внимание, что <p> выше может быть другим тегом, например <div>.

Поиск soup.find('p') следует избегать.

Конечный результат [456, 789].

Это немного сложно.

Как мы можем решить эту проблему?

Спасибо.

Ответы [ 3 ]

1 голос
/ 01 августа 2020

Этот скрипт распечатает все теги, которые имеют общее имя тега и атрибуты тега с тегом, содержащим строку «456»:

txt = '''
    <div class='mydiv'>
        <p style='xyz'>123</p>
        <p>456</p>
        <p style='xyz'>789</p>
        <p>abc</p>
    </div>'''

text_to_find = '456'
soup = BeautifulSoup(txt, 'html.parser')

tmp = soup.find(lambda t: t.contents and t.contents[0] == text_to_find)
if tmp:
    for tag in soup.find_all(lambda t: t.name == tmp.name and t.attrs == tmp.attrs):
        print(tag)

Выводит:

<p>456</p>
<p>abc</p>

Для ввода «123»:

<p style="xyz">123</p>
<p style="xyz">789</p>
0 голосов
/ 01 августа 2020

Попробуйте:

soup = BeautifulSoup("<div class='mydiv'><p style='xyz'>123</p><p>456</p><p style='xyz'>789</p><p>abc</p></div>", 'html5lib')

tags = soup.find_all()
for tag in tags:
    if tag.get('style'):
        tag.extract()

for tag in soup.select('html body'):
    print(tag.get_text('\n'))

распечатает:

456
abc
0 голосов
/ 01 августа 2020

На самом деле существует несколько способов, вот два примера, как вы можете найти то, что ищете:

from bs4 import BeautifulSoup

soup = BeautifulSoup("<div class='mydiv'><p style='xyz'>123</p><p>456</p><p style='xyz'>789</p><p>abc</p></div>", 'lxml')

# Find all tags first and then look for the one matching your string
found = [x for x in soup.findAll() if x.text == "456"]

for p in found:
  print(p)

# Using findAll functionality directly
found = soup.findAll(text="456")

for p in found:
  print(p)

456

456

Обратите внимание, что при использовании второго метода вы получаете NavigableString объектов, а не Tag объектов!

...