python - 在 python 中迭代带有美丽汤的行表

标签 python beautifulsoup

我正在尝试使用 beautiful soup 解析行表,并将每行的值保存在字典中。

一个问题是表的结构中有一些行作为节标题。因此,对于具有“header”类的任何行,我想定义一个名为“section”的变量。这是我所拥有的,但它不起作用,因为它说 ['class'] TypeError:字符串索引必须是整数

这是我所拥有的:

for i in credits.contents:
    if i['class'] == 'header':
        section = i.contents
        DATA_SET[section] = {}
    else:
        DATA_SET[section]['data_point_1'] = i.find('td', {'class' : 'data_point_1'}).find('p').contents
        DATA_SET[section]['data_point_2'] = i.find('td', {'class' : 'data_point_2'}).find('p').contents
        DATA_SET[section]['data_point_3'] = i.find('td', {'class' : 'data_point_3'}).find('p').contents

数据示例:

<table class="credits">
    <tr class="header">
        <th colspan="3"><h1>HEADER NAME</h1></th>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA</p></td>
        <td class="data_point_2"><p>DATA</p></td>
        <td class="data_point_3"><p>DATA</p></td>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA</p></td>
        <td class="data_point_2"><p>DATA</p></td>
        <td class="data_point_3"><p>DATA</p></td>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA</p></td>
        <td class="data_point_2"><p>DATA</p></td>
        <td class="data_point_3"><p>DATA</p></td>
    </tr>
    <tr class="header">
        <th colspan="3"><h1>HEADER NAME</h1></th>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA</p></td>
        <td class="data_point_2"><p>DATA</p></td>
        <td class="data_point_3"><p>DATA</p></td>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA</p></td>
        <td class="data_point_2"><p>DATA</p></td>
        <td class="data_point_3"><p>DATA</p></td>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA</p></td>
        <td class="data_point_2"><p>DATA</p></td>
        <td class="data_point_3"><p>DATA</p></td>
    </tr>
</table>

最佳答案

这是一种解决方案,对示例数据进行了轻微调整,以使结果更加清晰:

from BeautifulSoup import BeautifulSoup
from pprint import pprint

html = '''<body><table class="credits">
    <tr class="header">
        <th colspan="3"><h1>HEADER 1</h1></th>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA11</p></td>
        <td class="data_point_2"><p>DATA12</p></td>
        <td class="data_point_3"><p>DATA12</p></td>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA21</p></td>
        <td class="data_point_2"><p>DATA22</p></td>
        <td class="data_point_3"><p>DATA23</p></td>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA31</p></td>
        <td class="data_point_2"><p>DATA32</p></td>
        <td class="data_point_3"><p>DATA33</p></td>
    </tr>
    <tr class="header">
        <th colspan="3"><h1>HEADER 2</h1></th>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA11</p></td>
        <td class="data_point_2"><p>DATA12</p></td>
        <td class="data_point_3"><p>DATA13</p></td>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA21</p></td>
        <td class="data_point_2"><p>DATA22</p></td>
        <td class="data_point_3"><p>DATA23</p></td>
    </tr>
    <tr>
        <td class="data_point_1"><p>DATA31</p></td>
        <td class="data_point_2"><p>DATA32</p></td>
        <td class="data_point_3"><p>DATA33</p></td>
    </tr>
</table></body>'''

soup = BeautifulSoup(html)
rows = soup.findAll('tr')

section = ''
dataset = {}
for row in rows:
    if row.attrs:
        section = row.text
        dataset[section] = {}
    else:
        cells = row.findAll('td')
        for cell in cells:
            if cell['class'] in dataset[section]:
                dataset[section][ cell['class'] ].append( cell.text )
            else:
                dataset[section][ cell['class'] ] = [ cell.text ]

pprint(dataset)

产品:

{u'HEADER 1': {u'data_point_1': [u'DATA11', u'DATA21', u'DATA31'],
               u'data_point_2': [u'DATA12', u'DATA22', u'DATA32'],
               u'data_point_3': [u'DATA12', u'DATA23', u'DATA33']},
 u'HEADER 2': {u'data_point_1': [u'DATA11', u'DATA21', u'DATA31'],
               u'data_point_2': [u'DATA12', u'DATA22', u'DATA32'],
               u'data_point_3': [u'DATA13', u'DATA23', u'DATA33']}}

编辑调整您的解决方案

您的代码很简洁,只有几个问题。您在应该使用 textfindAll 的地方使用 contents ——我在下面修复了它:

soup = BeautifulSoup(html)
credits = soup.find('table')

section = ''
DATA_SET = {}

for i in credits.findAll('tr'):
    if i.get('class', '') == 'header':
        section = i.text
        DATA_SET[section] = {}
    else:
        DATA_SET[section]['data_point_1'] = i.find('td', {'class' : 'data_point_1'}).find('p').contents
        DATA_SET[section]['data_point_2'] = i.find('td', {'class' : 'data_point_2'}).find('p').contents
        DATA_SET[section]['data_point_3'] = i.find('td', {'class' : 'data_point_3'}).find('p').contents

print DATA_SET

请注意,如果连续的单元格具有相同的 data_point 类,则连续的行将替换前面的行。我怀疑这在您的真实数据集中不是问题,但这就是为什么您的代码会返回这个缩写结果:

{u'HEADER 2': {'data_point_2': [u'DATA32'],
               'data_point_3': [u'DATA33'],
               'data_point_1': [u'DATA31']},
 u'HEADER 1': {'data_point_2': [u'DATA32'],
               'data_point_3': [u'DATA33'],
               'data_point_1': [u'DATA31']}}

关于python - 在 python 中迭代带有美丽汤的行表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10659479/

相关文章:

python - 如何使用 python 在任何 X windows 的文本字段中正确输入 unicode 字符?

python - 获取没有内部子标签文本的 HTML 标签文本

python - 确定何时没有数据库行与 Python mysql.connector 匹配

python - 有没有办法在 python 中找到 "in"关键字匹配的索引

python - 无法安装 Beautifulsoup ("bs4 does not exist")

html - BeautifulSoup html.parser 不理解 img 标签

python - 在Python CSV Writer循环中一次写入标题

python - <for> 循环的切片函数

python - 在 pyspark 中不使用 pivot 进行分组的有效方法

python - 使用 Python 解析包含来自 AWS Lambda 的图像的 Base64 编码数据