如何使用BeautifulSoup获取表格中的第一个和第三个td?

6

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

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

上述HTML的问题在于BeautifulSoup将其读为一个标签。我需要提取第一个<td>和第三个<td>的值,分别为1和20。
不幸的是,我不知道该如何处理。我该如何让BeautifulSoup读取表格每行的第1个和第3个<td>标签?
更新:
我找到了问题所在。我使用的是html.parser而不是BeautifulSoup的默认解析器。一旦我切换到默认解析器,问题就消失了。我也使用了答案中列出的方法。
我还发现不同的解析器对错误代码非常敏感。例如,默认解析器拒绝读取192行之后的行,但是html5lib完成了任务。因此,如果您无法解析整个表格,请尝试使用lxml、html和html5lib。
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元素中(不是标签)。

您可以使用以下方式获取这些元素的内容:

>>> 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%'

我尝试了这个,但结果是[<td>1<td><td>20<td>5%</td></td></td></td>,<td><td>20<td>5%</td></td></td>,<td>20<td>5%</td></td>,<td>5%</td>] - Alex Ketay
没问题 :-) 你可能已经发现了,使用'html.parser'解析HTML时,它会被解释为格式良好的XHTML(如上所述),而不是格式错误的HTML,因此在你的第一个结果中出现了嵌套的'td'元素。 - Zero Piraeus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接