python-3.x - 如何用 BeautifulSoup4 解析表格并优雅地打印?
问题描述
<table class="gridtable">
<tbody>
<tr>
<th>Store #</th><th>City Name</th><th>Orders</th></tr>
<tr><td>1</td><td style="text-align:left">Phoenix</td><td>70</td></tr>
<tr><td>2</td><td style="text-align:left">Columbus</td><td>74</td></tr>
<tr><td>3</td><td style="text-align:left">New York</td><td>112</td></tr>
<tr><td></td><td>TOTAL</td><td>256</td></tr></tbody>
</table>
我玩过以下变体,但不能:
1)显示所有行
2) 优雅地显示结果,就像我在实际页面上查看时的样子
import requests
from bs4 import BeautifulSoup
req = requests.get('Page.html')
soup = BeautifulSoup(req.content, 'html.parser')
tables = soup.find_all('table')
table = tables[0]
print(table.text)
解决方案
将您的文本数据收集到单个行和单元格的平面数组中。转置它,因此每列的所有内容都收集到row中。创建一个数组,其中包含每(原始)列最长项目的长度。在打印行时,使用此数据分隔每个单元格。在代码中:
from bs4 import BeautifulSoup
content = '''
<table class="gridtable">
<tbody>
<tr>
<th>Store #</th><th>City Name</th><th>Orders</th></tr>
<tr><td>1</td><td style="text-align:left">Phoenix</td><td>70</td></tr>
<tr><td>2</td><td style="text-align:left">Columbus</td><td>74</td></tr>
<tr><td>3</td><td style="text-align:left">New York</td><td>112</td></tr>
<tr><td></td><td>TOTAL</td><td>256</td></tr></tbody>
</table>
'''
def print_table_nice(table):
cells = [[cell.text for cell in row.find_all(['td','th'])] for row in table.find_all('tr')]
transposed = list(map(list, zip(*cells)))
widths = [str(max([len(str(item)) for item in items])) for items in transposed]
for row in cells:
print (' '.join(("{:"+width+"s}").format(item) for width,item in zip(widths,row)))
soup = BeautifulSoup(content, 'html.parser')
tables = soup.find_all('table')
table = tables[0]
print_table_nice(table)
结果:
Store # City Name Orders
1 Phoenix 70
2 Columbus 74
3 New York 112
TOTAL 256
这似乎与您在控制台上所做的一样优雅。(要添加垂直线,只需用 a|
而不是空格连接行。)
我内联了表数据,因为我无权访问您的Page.html
,但访问表数据似乎不是这里的问题。
哦,让我们在周围添加线条。只是因为我可以:
def print_table_nice(table):
header = [cell.text for cell in table.select('tr th')]
cells = [[cell.text for cell in row.select('td')] for row in table.select('tr') if row.select('td')]
table = [header]+cells
transposed = list(map(list, zip(*table)))
widths = [str(max([len(str(item)) for item in items])) for items in transposed]
print ('+'+('-+-'.join('-'*int(width) for width in widths))+'+')
print ('|'+(' | '.join(("{:"+width+"s}").format(item) for width,item in zip(widths,header)))+'|')
print ('+'+('-+-'.join('-'*int(width) for width in widths))+'+')
for row in cells:
print ('|'+(' | '.join(("{:"+width+"s}").format(item) for width,item in zip(widths,row)))+'|')
print ('+'+('-+-'.join('-'*int(width) for width in widths))+'+')
事实证明这是一个有趣的并发症,因为这需要将th
与行分开td
。但是,对于多行行不会按原样工作。那么,结果是:
+--------+-----------+-------+
|Store # | City Name | Orders|
+--------+-----------+-------+
|1 | Phoenix | 70 |
|2 | Columbus | 74 |
|3 | New York | 112 |
| | TOTAL | 256 |
+--------+-----------+-------+
推荐阅读
- python - 尝试将“pending_xref”节点附加到signode时发生异常
- database - JavaFX label.getText() 不返回任何内容
- filter - 如何在 Google 表格的 FILTER 中应用多个条件?
- python - 熊猫的几个月
- swift - 在 macOS 中截屏不保存图像
- java - 代码无法运行,说有问题,只说“找不到符号”
- typescript - 在转换为 typescript 时修复 Ember 加载初始化器
- c - 调用strtok的段错误?
- python - 在 raspberrypi 中安装 MySql 并使用 python3 将数据放入表中
- c# - 将变量与 UI 控件同步的最佳方式是什么?