Как разобрать таблицу с BeautifulSoup4 и элегантно распечатать? - PullRequest
0 голосов
/ 25 октября 2018
<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)

1 Ответ

0 голосов
/ 26 октября 2018

Соберите свои текстовые данные в плоский массив отдельных строк и ячеек.Перенесите это так, чтобы все в столбце было собрано в строку .Создайте массив, содержащий длину самого длинного элемента в (первоначально) столбце.Используйте эти данные для разметки каждой ячейки при печати строк.В коде:

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

, который выглядит примерно так же элегантно, как и на консоли.(Чтобы добавить вертикальные линии, просто объедините строки с | вместо пробела.)

Я встроил данные таблицы, потому что у меня нет доступа к вашему 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   |
+--------+-----------+-------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...