Можно ли перебирать HTML-дерево в BeautifulSoup4? - PullRequest
0 голосов
/ 09 марта 2019

Пример HTML ('x.html' во фрагменте Python):

<table>
    <tr>
        <td>a</td>
        <td>b</td>
        <table><tr><td>c</td></tr></table>
    </tr>
</table>

Я хочу получить список из трех столбцов из одной строки таблицы:

[
  '<td>a</td>',
  '<td>b</td>',
  '<table><tr><td>c</td></tr></table>'
]

Я пытался просто перебрать объект BeautifulSoup, но он возвращает весь HTML и пустую (ну, '\n') строку.

In [9]: soup = BeautifulSoup(open('x.html').read(), 'html.parser')
In [10]: for a in soup: 
    ...:     print(type(a)) 
    ...:                                                                                                                                                                                                    
<class 'bs4.element.Tag'>
<class 'bs4.element.NavigableString'>

Я также пытался использовать метод find_all(), но он находит вложенный <td>c</td>, который я не хочу видеть в результатах:

In [24]: len(soup.find_all('td'))                                                                                                                                                                           
Out[24]: 4  # <-- I need 3 things, not 4

Я думал, что параметр find / find_all recursive касается вложенных элементов, но я не понимаю, работает ли он вообще:

Signature: soup.find_all(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs)
In [26]: len(soup.find_all('td', recursive=False))                                                                                                                                                          
Out[26]: 0

Может, написание xml.sax парсера будет проще?

1 Ответ

1 голос
/ 09 марта 2019

Как @Danielle предложил в комментарии, вы можете получить .contents внешнего tr.Но так как вы читаете из этого файла, вы получите ряд "\n" и других нежелательных элементов с этим.Вы можете проверить, если isinstance(x,Tag), чтобы получить только содержимое тега.

В некоторых ситуациях с неверным html может не быть простого решения, подобного этому.В этих случаях вы также можете передать пользовательскую функцию find_all.Например,Данные, которые вы ищете, также могут быть получены с помощью этой логики - Найти все теги td и table в первой таблице файла.Конечно, логика может отличаться от этого, но вы поняли.

from bs4 import BeautifulSoup
from bs4 import Tag
soup = BeautifulSoup(open('x.html').read(), 'html.parser')
#solution 1
print([x for x in soup.find('tr').contents if isinstance(x,Tag)])
#solution 2 with a custom function
first_table=soup.find('table')
def is_td_or_table(item):
    if isinstance(item,Tag):
        if item.name in ['td','table'] and item.find_parent("table") is first_table:
            return True
print(first_table.find_all(is_td_or_table))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...