Я пытаюсь очистить все внутренние html от элементов <p> на веб-странице, используя BeautifulSoup. Есть внутренние теги, но мне все равно, я просто хочу получить внутренний текст.

Например, для:

<p>Red</p>
<p><i>Blue</i></p>
<p>Yellow</p>
<p>Light <b>green</b></p>

Как я могу извлечь:

Red
Blue
Yellow
Light green

Ни .string, ни .contents[0] не делают то, что мне нужно. И не .extract(), потому что я не хочу заранее указывать внутренние теги - я хочу иметь дело с любыми возможными.

Есть ли в BeautifulSoup метод типа «просто получить видимый HTML»?

----ОБНОВИТЬ------

По совету, стараюсь:

soup = BeautifulSoup(open("test.html"))
p_tags = soup.findAll('p',text=True)
for i, p_tag in enumerate(p_tags): 
    print str(i) + p_tag

Но это не помогает - это распечатывает:

0Red
1

2Blue
3

4Yellow
5

6Light 
7green
8
42
AP257 2 Июн 2010 в 14:58

5 ответов

Лучший ответ

Краткий ответ: soup.findAll(text=True)

На этот вопрос уже есть ответ, здесь, в StackOverflow и в Документация BeautifulSoup.

ОБНОВЛЕНИЕ:

Чтобы уточнить, рабочий кусок кода:

>>> txt = """\
<p>Red</p>
<p><i>Blue</i></p>
<p>Yellow</p>
<p>Light <b>green</b></p>
"""
>>> import BeautifulSoup
>>> BeautifulSoup.__version__
'3.0.7a'
>>> soup = BeautifulSoup.BeautifulSoup(txt)
>>> for node in soup.findAll('p'):
    print ''.join(node.findAll(text=True))

Red
Blue
Yellow
Light green
69
Community 23 Май 2017 в 11:55

Обычно данные, удаленные с веб-сайта, содержат теги. Чтобы избежать этих тегов и отображать только текстовое содержимое, вы можете использовать текстовый атрибут.

Например,

    from BeautifulSoup import BeautifulSoup

    import urllib2 
    url = urllib2.urlopen("https://www.python.org")

    content = url.read()

    soup = BeautifulSoup(content)

    title = soup.findAll("title")

    paragraphs = soup.findAll("p")

    print paragraphs[1] //Second paragraph with tags

    print paragraphs[1].text //Second paragraph without tags

В этом примере я собираю все абзацы с сайта Python и отображаю его с тегами и без тегов.

3
Codemaker 10 Июл 2018 в 13:12

Сначала преобразуйте html в строку, используя str. Затем используйте следующий код с вашей программой:

import re
x = str(soup.find_all('p'))
content = str(re.sub("<.*?>", "", x))

Это называется regex. Этот удалит все, что находится между двумя тегами html (включая теги).

0
toyotasupra 23 Дек 2017 в 16:15

Принятый ответ отличный, но ему уже 6 лет, поэтому вот текущая Beautiful Soup 4 версия этого ответа:

>>> txt = """\
<p>Red</p>
<p><i>Blue</i></p>
<p>Yellow</p>
<p>Light <b>green</b></p>
"""
>>> from bs4 import BeautifulSoup, __version__
>>> __version__
'4.5.1'
>>> soup = BeautifulSoup(txt, "html.parser")
>>> print("".join(soup.strings))

Red
Blue
Yellow
Light green
11
Jaymon 14 Дек 2016 в 10:51

Я наткнулся на эту же проблему и хотел поделиться версией этого решения в 2019 году. Может быть, это кому-нибудь поможет.

# importing the modules
from bs4 import BeautifulSoup
from urllib.request import urlopen

# setting up your BeautifulSoup Object
webpage = urlopen("https://insertyourwebpage.com")
soup = BeautifulSoup( webpage.read(), features="lxml")
p_tags = soup.find_all('p')


for each in p_tags: 
    print (str(each.get_text()))

Обратите внимание, что мы сначала печатаем содержимое массива один за другим, а затем вызываем метод get_text (), который удаляет теги из текста, чтобы мы только распечатывали текст.

Также:

  • лучше использовать обновленную функцию find_all () в bs4, чем более старую findAll ()
  • urllib2 был заменен urllib.request и urllib.error, см. здесь.

Теперь ваш вывод должен быть:

  • Красный
  • Синий
  • Желтый
  • Светлый

Надеюсь, что это помогает кому-то искать обновленное решение.

5
erddev 9 Авг 2019 в 18:00