BeautifulSoup: получить содержимое определенной таблицы

Мой местный аэропорт позорно блокирует пользователей без IE и выглядит ужасно. Я хочу написать сценарии Python, которые будут получать содержимое страниц прибытия и отправления каждые несколько минут и отображать их в более читаемом виде.

Я предпочитаю следующие инструменты: механизировать, чтобы заставить сайт поверить в то, что я использую IE, и BeautifulSoup для анализа страницы для получения таблицы данных о рейсах.

Честно говоря, я запутался в документации BeautifulSoup и не могу понять, как получить таблицу (название которой мне известно) из всего документа и как получить список строк из этой таблицы.

Есть идеи?


person Adam Matan    schedule 29.05.2010    source источник


Ответы (3)


Это не конкретный код, который вам нужен, а просто демонстрация того, как работать с BeautifulSoup. Он находит таблицу с идентификатором «Table1» и получает все ее элементы tr.

html = urllib2.urlopen(url).read()
bs = BeautifulSoup(html)
table = bs.find(lambda tag: tag.name=='table' and tag.has_attr('id') and tag['id']=="Table1") 
rows = table.findAll(lambda tag: tag.name=='tr')
person Ofri Raviv    schedule 29.05.2010
comment
Это действительно круто, я не знал, что вы можете передать лямбды, чтобы найти. - person goggin13; 29.05.2010
comment
Действительно здорово! Проверьте свой почтовый ящик на Facebook, я отправил вам сообщение. - person Adam Matan; 29.05.2010
comment
любые идеи, как перейти к конкретной таблице, когда нет идентификатора или заголовка, чтобы различать... например.. Я хочу, чтобы третья таблица была в файле html... (других индикаторов нет). - person ihightower; 08.06.2012
comment
Мне нравится это решение намного больше, так как оно кажется более ясным в намерениях! - person stephenmm; 17.12.2013
comment
Вы даже можете связать команды поиска внутри лямбды (чтобы лучше фильтровать, так как у меня было несколько таблиц, но у них не было идентификаторов)! table = soup.find(lambda tag: tag.name=='table' and tag.find(lambda ttag: ttag.name=='th' and ttag.text=='Common Name')) - person nmz787; 08.12.2017
comment
что делать, если у таблицы нет имени? @Офри Равив - person alper; 15.01.2018
comment
К вашему сведению, has_key устарел. Вместо этого используйте has_attr(id). Я также отредактирую исходный ответ. - person PiperWarrior; 10.03.2018
comment
как вы могли игнорировать теги 'th', если внутри ‹tr› есть заголовки вложенных таблиц ‹th›? ‹tr›‹th class=wsod_firstCol›‹div class=sortLink onclick=common.updateQueryString('order', 'd');›Company‹span class=sortOrder style=background-position: 0 -6px;›‹!- -индикатор порядка--›‹/span›‹/div›‹/th›‹th›Цена‹/th›‹th›Изменение‹/th›‹th›% Изменение‹/th›‹th›P/E‹ /th›‹th›Объем‹/th›‹th›YTD‹br/›change‹/th›‹/tr› ‹tr›‹td class=wsod_firstCol›‹a class=wsod_symbol href=//money.cnn. com/quote/quote.html?symb=MMM›MMM‹/a› 3M‹/td›‹td›‹span - person neif; 09.04.2019

Вот рабочий пример универсального <table>. (Хотя ваша страница не используется из-за необходимости выполнения JavaScript для загрузки данных таблицы)

Извлечение данных таблицы из здесь ВВП (валовой внутренний продукт) по странам.

htmltable = soup.find('table', { 'class' : 'table table-striped' })
# where the dictionary specify unique attributes for the 'table' tag

Ниже функция анализирует сегмент html, начинающийся с тега <table>, за которым следуют несколько тегов <tr> (строки таблицы) и внутренние теги <td> (данные таблицы). Он возвращает список строк с внутренними столбцами. Принимает только один <th> (заголовок/данные таблицы) в первой строке.

def tableDataText(table):    
    """Parses a html segment started with tag <table> followed 
    by multiple <tr> (table rows) and inner <td> (table data) tags. 
    It returns a list of rows with inner columns. 
    Accepts only one <th> (table header/data) in the first row.
    """
    def rowgetDataText(tr, coltag='td'): # td (data) or th (header)       
        return [td.get_text(strip=True) for td in tr.find_all(coltag)]  
    rows = []
    trs = table.find_all('tr')
    headerow = rowgetDataText(trs[0], 'th')
    if headerow: # if there is a header row include first
        rows.append(headerow)
        trs = trs[1:]
    for tr in trs: # for every table row
        rows.append(rowgetDataText(tr, 'td') ) # data row       
    return rows

С его помощью получаем (первые две строки).

list_table = tableDataText(htmltable)
list_table[:2]

[['Rank',
  'Name',
  "GDP (IMF '19)",
  "GDP (UN '16)",
  'GDP Per Capita',
  '2019 Population'],
 ['1',
  'United States',
  '21.41 trillion',
  '18.62 trillion',
  '$65,064',
  '329,064,917']]

Его можно легко преобразовать в pandas.DataFrame для более сложных манипуляций.

import pandas as pd

dftable = pd.DataFrame(list_table[1:], columns=list_table[0])
dftable.head(4)

введите описание изображения здесь

person eusoubrasileiro    schedule 07.10.2019

person    schedule
comment
любые идеи, как перейти к конкретной таблице, когда нет идентификатора или заголовка, чтобы различать... например.. Я хочу, чтобы третья таблица была в файле html... (других индикаторов нет). - person ihightower; 08.06.2012
comment
@ihightower: soup.find('table')[2] принесет тебе третий table. (Вы бы хотели проверить длину, прежде чем делать это, просто на всякий случай.) - person hamstu; 13.09.2013