【发布时间】:2018-07-01 18:33:18
【问题描述】:
首先,我阅读了Parsing a table with rowspan and colspan。我什至回答了这个问题。请在将其标记为重复之前阅读。
<table border="1">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td rowspan="2">C</td>
<td rowspan="1">D</td>
</tr>
<tr>
<td>E</td>
<td>F</td>
</tr>
<tr>
<td>G</td>
<td>H</td>
</tr>
</table>
它会像这样渲染
+---+---+---+
| A | B | |
+---+---+ |
| | D | |
+ C +---+---+
| | E | F |
+---+---+---+
| G | H | |
+---+---+---+
<table border="1">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td rowspan="2">C</td>
<td rowspan="2">D</td>
</tr>
<tr>
<td>E</td>
<td>F</td>
</tr>
<tr>
<td>G</td>
<td>H</td>
</tr>
</table>
但是,这将呈现为这样。
+---+---+-------+
| A | B | |
+---+---+-------+
| | | |
| C | D +---+---+
| | | E | F |
+---+---+---+---+
| G | H | |
+---+---+---+---+
我上一个答案的代码只能解析第一行中定义了所有列的表。
def table_to_2d(table_tag):
rows = table_tag("tr")
cols = rows[0](["td", "th"])
table = [[None] * len(cols) for _ in range(len(rows))]
for row_i, row in enumerate(rows):
for col_i, col in enumerate(row(["td", "th"])):
insert(table, row_i, col_i, col)
return table
def insert(table, row, col, element):
if row >= len(table) or col >= len(table[row]):
return
if table[row][col] is None:
value = element.get_text()
table[row][col] = value
if element.has_attr("colspan"):
span = int(element["colspan"])
for i in range(1, span):
table[row][col+i] = value
if element.has_attr("rowspan"):
span = int(element["rowspan"])
for i in range(1, span):
table[row+i][col] = value
else:
insert(table, row, col + 1, element)
soup = BeautifulSoup('''
<table>
<tr><th>1</th><th>2</th><th>5</th></tr>
<tr><td rowspan="2">3</td><td colspan="2">4</td></tr>
<tr><td>6</td><td>7</td></tr>
</table>''', 'html.parser')
print(table_to_2d(soup.table))
我的问题是如何将表格解析为二维数组,该数组准确地表示它在浏览器中的呈现方式。或者有人可以解释一下浏览器如何呈现表格也可以。
【问题讨论】:
-
您可能需要对表格进行两次遍历:一次确定其真实尺寸,一旦知道,再进行一次遍历以提取数据。
-
@JohnGordon 跑两遍不是问题。但我需要了解渲染表格的规则是什么。没有它,我会认为第二个代码有 4 行而不是 3 行。
-
只是好奇,这样的解析器有什么实际需要吗?在我看来,使用自定义逻辑处理跨度通常比以后从列表中获取任何信息要好。
标签: python html html-table