1

美しいスープを使用して行のテーブルを解析し、各行の値を辞書に保存しようとしています。

問題の 1 つは、テーブルの構造にセクション ヘッダーとしていくつかの行があることです。したがって、「header」クラスの行については、「section」という変数を定義したいと思います。これが私が持っているものですが、['class']と言っているために機能していませんTypeError: string indices must be integers

ここに私が持っているものがあります:

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>
4

1 に答える 1

3

結果がより明確になるように、サンプルデータをわずかに調整した1つのソリューションを次に示します。

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']}}

ソリューションの適応を編集

あなたのコードはきちんとしていて、いくつかの問題しかありません。使用する必要contentsがある場所で使用するtextか、findAll次のように修正しました。

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']}}
于 2012-05-18T21:37:27.453 に答える