BeautifulSoup, словарь из таблицы HTML

Я пытаюсь очистить данные таблицы с веб-сайта.

Вот простая примерная таблица:

t = '<html><table>' +\
    '<tr><td class="label"> a </td> <td> 1 </td></tr>' +\
    '<tr><td class="label"> b </td> <td> 2 </td></tr>' +\
    '<tr><td class="label"> c </td> <td> 3 </td></tr>' +\
    '<tr><td class="label"> d </td> <td> 4 </td></tr>' +\
    '</table></html>'

Желаемый результат синтаксического анализа: {' a ': ' 1 ', ' b ': ' 2 ', ' c ': ' 3 ', ' d ' : ' 4' }


Это моя ближайшая попытка:

for tr in s.findAll('tr'):
  k, v = BeautifulSoup(str(tr)).findAll('td')
  d[str(k)] = str(v)

Результат:

{'<td class="label"> a </td>': '<td> 1 </td>', '<td class="label"> d </td>': '<td> 4 </td>', '<td class="label"> b </td>': '<td> 2 </td>', '<td class="label"> c </td>': '<td> 3 </td>'}

Я знаю о параметре text=True для findAll(), но при его использовании я не получаю ожидаемых результатов.

Я использую Python 2.6 и BeautifulSoup3.


person jon    schedule 10.08.2012    source источник
comment
привет! Большое спасибо за этот отличный пример - это действительно очень полезный и отличный пример - он показывает мне, как работать с базовыми структурами данных Python. Кстати, можем ли мы применить этот замечательный мини-урок к примеру из реального мира - например, к таблице в Википедии - я рад услышать от вас - с уважением ноль   -  person zero    schedule 05.07.2020


Ответы (5)


Попробуй это:

from BeautifulSoup import BeautifulSoup, Comment

t = '<html><table>' +\
    '<tr><td class="label"> a </td> <td> 1 </td></tr>' +\
    '<tr><td class="label"> b </td> <td> 2 </td></tr>' +\
    '<tr><td class="label"> c </td> <td> 3 </td></tr>' +\
    '<tr><td class="label"> d </td> <td> 4 </td></tr>' +\
    '</table></html>'

bs = BeautifulSoup(t)

results = {}
for row in bs.findAll('tr'):
    aux = row.findAll('td')
    results[aux[0].string] = aux[1].string

print results
person mvillaress    schedule 10.08.2012

BeautifulSoup и Python развились, поэтому, если кто-то придет сюда с более новыми версиями:

Python>=3.7
BeautifulSoup>=4.7

Вот обновленный код, который работает:

# import bs4 and create your 'soup' object

table = soup.find('table')

headers = [header.text for header in table.find_all('th')]
results = [{headers[i]: cell for i, cell in enumerate(row.find_all('td'))}
           for row in table.find_all('tr')]
person martin-martin    schedule 01.07.2019
comment
привет, дорогой Мартин Мартин. - отлично: мне нравится этот подход: в данный момент я изучаю python, и мне очень полезно делать это с bs4: ваш код показывает, как создать суп-объект: - большое спасибо за это отличный пример — это действительно очень полезно и отличный пример — он показывает мне, как работать с базовыми структурами данных Python. Кстати, можем ли мы применить этот замечательный мини-урок к примеру из реального мира - например, к таблице в Википедии - я рад услышать от вас - с уважением ноль - person zero; 05.07.2020
comment
Здравствуйте, @zero. Ознакомьтесь с руководством по Beautiful Soup: создание веб-скребка на Python для примера, который проведет вас через весь процесс парсинга на реальном примере. Надеюсь, это поможет, и продолжайте учиться! :) - person martin-martin; 07.07.2020

Если вы очищаете таблицу, у нее есть явные «thead» и «tbody», например:

<table>
    <thead>
        <tr>
            <th>Total</th>
            <th>Finished</th>
            <th>Unfinished</th>
        </tr>
    </thead>
    <tbody>
        <tr> <td>63</td> <td>33</td> <td>2</td> </tr>
        <tr> <td>69</td> <td>29</td> <td>3</td> </tr>
        <tr> <td>57</td> <td>28</td> <td>1</td> </tr>
    </tbody>
</table>

Вы можете использовать следующее:

headers = [header.text_content() for header in table.cssselect("thead tr th")]
results = [{headers[i]: cell.text_content() for i, cell in enumerate(row.cssselect("td"))} for row in table.cssselect("tbody tr")]

Это произведет:

[
  {"Total": "63", "Finished": "33", "Unfinished": "2"},
  {"Total": "69", "Finished": "29", "Unfinished": "3"},
  {"Total": "57", "Finished": "28", "Unfinished": "1"}
]

P.S. Это использует lxml.html. Если вы используете BeautifulSoup, замените «.text_content()» на «.string» и «.cssselect» на «.findAll».

person Al Johri    schedule 30.11.2014

Вы можете следовать тому же подходу, что и mvillaress, но немного улучшить его, используя Понятия списка:

from BeautifulSoup import BeautifulSoup

t = '<html><table>' +\
    '<tr><td class="label"> a </td> <td> 1 </td></tr>' +\
    '<tr><td class="label"> b </td> <td> 2 </td></tr>' +\
    '<tr><td class="label"> c </td> <td> 3 </td></tr>' +\
    '<tr><td class="label"> d </td> <td> 4 </td></tr>' +\
    '</table></html>'

bs = BeautifulSoup(t)
tds = [row.findAll('td') for row in bs.findAll('tr')]
results = { td[0].string: td[1].string for td in tds }
print results
person rjfv    schedule 18.11.2014

Вот решение, которое, я считаю, ближе к исходной попытке:

d={}
for tr in soup.findAll('tr'):
    key = tr.text.split()[0]
    val = tr.text.split()[1]
    d[key] = val

print(d)
person codedmsg    schedule 17.03.2021