6

我目前正在使用 Python 和 BeautifulSoup 来抓取一些网站数据。我正在尝试从格式如下的表格中提取单元格:

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

上述 HTML 的问题在于 BeautifulSoup 将其作为一个标签读取。我需要从 first<td>和 third中提取值<td>,分别为 1 和 20。

不幸的是,我不知道该怎么做。如何让 BeautifulSoup 读取<td>表格每一行的第一个和第三个标签?

更新:

我解决了这个问题。我使用html.parser的是 BeautifulSoup 而不是默认值。一旦我切换到默认值,问题就消失了。我也使用了答案中列出的方法。

我还发现,不同的解析器对损坏的代码非常敏感。例如,默认解析器拒绝读取过去的第 192 行,但html5lib完成了工作。所以尝试使用lxml, htmlhtml5lib如果您在解析整个表时遇到问题。

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 分别位于第一个和第三个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 回答