Как я могу заставить Beautifulsoup печатать текст из абзацев, вложенных внутри div?

#python #web-scraping #beautifulsoup

#python #веб-очистка #beautifulsoup

Вопрос:

Я новичок в веб-очистке и использовании beautiful soup 4. Я пытался получить только текст, напечатанный внутри тегов <p></p>, которые вложены в div. Я могу заставить их печатать, но теги все еще появляются, и beautiful soup не позволяет мне использовать функцию .text для извлечения текста из тегов абзаца. Есть ли лучший способ сделать это или я просто делаю это неправильно?

 import requests
from bs4 import BeautifulSoup as soup

url = "https://www.wuxiaworld.com/novel/tales-of-demons-and-gods/tdg-chapter-1"
headers = {'User-Agent': 'Mozilla/5.0'}

req = requests.get(url, headers=headers)
src = req.content
print(req.status_code)
print()
bs4soup = soup(src, 'lxml')
bs4soup.prettify()

# div = bs4soup.find('div', attrs={'id': 'chapter-content'})
# par = div.find_all('p')
# print(par)  #  This just prints all of the <p> tags on the same line.

for paragraph in bs4soup.find('div', attrs={'id': 'chapter-content'}):
    print(paragraph)
 

Вот как выглядит мой вывод

 <p><strong>Chapter 1 - Reborn</strong></p>
<p><span style="">On the colossal St. Ancestral Mountain range, sunlight shined through the gap between the mountains into the deep canyons. On the hillside beside the valley, some snow remained.</span></p>
<p><span style="">Even though it’s already the early summer, the snow has yet to melt. The cold here is exceptionally long. The roars of beasts can occasionally be heard.</span></p>
 

и так продолжается для всех строк в абзаце.

Я попытался использовать текстовую функцию, встроенную в Beautiful Soup, но когда я добавил ее в paragraph.text, она выдает AttributeError: 'NavigableString' object has no attribute 'text'

Каков наилучший способ решения этой проблемы?

Ответ №1:

Поскольку структура страницы выглядит примерно так:

 <div id="chapter-content">
    <script></script>
    <p></p>
    <p></p>
    ...
</div>
 

Вы можете использовать .find_all() метод для получения всех p тегов и просто печатать текст из этих тегов:

 for paragraph in bs4soup.find('div', attrs={'id': 'chapter-content'}).find_all('p'):
    print(paragraph.text)
 

Вывод будет выглядеть следующим образом:

 Chapter 1 - Reborn
On the colossal St. Ancestral Mountain range, sunlight shined through the gap between the mountains into the deep canyons. On the hillside beside the valley, some snow remained.
Even though it’s already the early summer, the snow has yet to melt. The cold here is exceptionally long. The roars of beasts can occasionally be heard.
....
 

Ответ №2:

Вы получаете ошибку, потому что вы предсказываете, что все дочерние элементы выбранного div равны p, к сожалению, нет!

Вы можете попробовать, написав этот код:

 main_div = bs4soup.find('div', attrs={'id': 'chapter-content'}) # recover it first.
for item in main_div:
    print(item.name)
 

Затем вы увидите теги, отличные от p, и вы получаете сообщение об ошибке, потому что некоторые из них не содержат атрибута .text .

Чтобы решить эту проблему, вы можете проверить каждый тег, является ли он p внутри цикла:

 main_div = bs4soup.find('div', attrs={'id': 'chapter-content'})
for item in main_div:
    if item.name == "p": # Here the work
       print(item.text)
 

Или продолжайте находить все теги p внутри этого div, что я рекомендую.

 main_div = bs4soup.find('div', attrs={'id': 'chapter-content'})
p_tags = main_div.find_all("p") # You got only p tags
# Each p tag have .text attribute, looping now is secure
for p in p_tage:
    print(p.text)
 

Комментарии:

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

2. Я сделал это, и я улучшил качество своего поста, спасибо вам, кстати, за то, что позаботились о качестве МОЕГО поста.

3. Вау, большое вам спасибо. Объяснение ошибки действительно помогает. Я продолжал задаваться вопросом, почему .text не работает! Это отлично очищает его.