6

現在、Python と BeautifulSoup を使用して Web サイトのデータをスクレイピングしています。次のようにフォーマットされたテーブルからセルを取得しようとしています:

<tr><td>1<td><td>20<td>5%</td></td></td></td></tr>

上記の HTML の問題は、BeautifulSoup がそれを 1 つのタグとして読み取ることです。<td>最初の と 3 番目の から値を取得する必要があり<td>ます。それぞれ 1 と 20 になります。

残念ながら、これについてどうすればよいかわかりません。<td>テーブルの各行の1 番目と 3 番目のタグを BeautifulSoup に読み取らせるにはどうすればよいですか?

アップデート:

私は問題を理解しました。html.parserBeautifulSoupのデフォルトの代わりに使用していました。デフォルトに切り替えると、問題はなくなりました。また、回答に記載されている方法を使用しました。

また、さまざまなパーサーが壊れたコードで非常に気まぐれであることもわかりました。たとえば、デフォルトのパーサーは 192 行目以降の読み取りを拒否しましたhtml5libが、ジョブは完了しました。テーブル全体の解析に問題がある場合はlxml、 、html、およびを使用してみてください。html5lib

4

1 に答える 1

15

それはあなたがそこに持っているHTMLの厄介な部分です. 表の行と表のセルのセマンティクスを少し無視して純粋な XML として扱うと、その構造は次のようになります。

<tr>
  <td>1
    <td>
      <td>20
        <td>5%</td>
      </td>
    </td>
  </td>
</tr>

ただし、BeautifulSoup は HTML テーブルのセマンティクスを認識しており、代わりに次のように解析します。

<tr>
  <td>1        <!-- an IMPLICITLY (no closing tag) closed td element -->
  <td>         <!-- as above -->
  <td>20       <!-- as above -->
  <td>5%</td>  <!-- an EXPLICITLY closed td element -->
  </td>        <!-- an error; ignore this -->
  </td>        <!-- as above -->
  </td>        <!-- as above -->
</tr>

...あなたが言うように、 1 と 20 はそれぞれ最初と 3 番目tdの要素 (タグではありません) にあります。

tdこれらの要素の内容は、次のように取得できます。

>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup("<tr><td>1<td><td>20<td>5%</td></td></td></td></tr>")
>>> tr = soup.find("tr")
>>> tr
<tr><td>1</td><td></td><td>20</td><td>5%</td></tr>
>>> td_list = tr.find_all("td")
>>> td_list
[<td>1</td>, <td></td>, <td>20</td>, <td>5%</td>]
>>> td_list[0]  # Python starts counting list items from 0, not 1
<td>1</td>
>>> td_list[0].text
'1'
>>> td_list[2].text
'20'
>>> td_list[3].text
'5%'
于 2013-08-14T12:30:39.380 に答える