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

#python #beautifulsoup

Вопрос:

У меня есть этот образец-html:

 soup=BeautifulSoup('''<ul>
 <li class=“item">
 <span class="letter">A. </span>
Text I want </li>
 <li class="item">
 <span class="letter">B.</span>                           
Second text I want</li></ul>''')
 

Я пытаюсь извлечь «Текст, который я хочу» и «Второй текст, который я хочу», игнорируя теги span. До сих пор то, что я сделал:

 soup.li.find_all(text=True,recursive=False)
 

Который возвращается ['n', 'nText I want '] .

Если я попытаюсь:

 for s in soup.ul:
    print(s.find(text=True,recursive=False))
 

Я получаю сообщение об ошибке:

 TypeError: find() takes no keyword arguments
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-93-f253cd430e83> in <module>
      1 for s in soup.ul:
----> 2     print(s.find(text=True,recursive=False))

TypeError: find() takes no keyword arguments
 

Мы будем признательны за любую помощь.

Ответ №1:

Вы можете использовать понимание списка для извлечения текстов:

 from bs4 import BeautifulSoup

soup = BeautifulSoup(
    """<ul>
 <li class="item">
 <span class="letter">A. </span>
Text I want </li>
 <li class="item">
 <span class="letter">B.</span>                           
Second text I want</li>""",
    "html.parser",
)

texts = [
    txt
    for li in soup.select("li.item")
    for t in li.find_all(text=True, recursive=False)
    if (txt := t.strip())
]
print(texts)
 

С принтами:

 ['Text I want', 'Second text I want']
 

Или удалите <span> первый, а затем получите текст:

 for span in soup.select("span"):
    span.extract()

texts = [li.get_text(strip=True) for li in soup.select("li.item")]
print(texts)
 

С принтами:

 ['Text I want', 'Second text I want']
 

Или: Найдите <span> , а затем .find_next_sibling(text=True) :

 texts = [
    li.find_next_sibling(text=True).strip()
    for li in soup.select("li.item span")
]
print(texts)
 

С принтами:

 ['Text I want', 'Second text I want']