Как перебрать html-таблицу-набор данных в Python - PullRequest
5 голосов
/ 07 января 2011

Я впервые здесь постер, пытаюсь приобрести некоторые навыки Python; пожалуйста, будь добр ко мне: -)

Хотя я не совсем незнаком с концепциями программирования (я раньше возился с PHP), переход на Python оказался для меня несколько сложным. Я предполагаю, что это в основном связано с тем, что мне не хватает большинства - если не всех - базового понимания общих «шаблонов проектирования» (?) И тому подобного.

Сказав это, это проблема. Часть моего текущего проекта включает в себя написание простого скребка с использованием Beautiful Soup. Обрабатываемые данные имеют структуру, аналогичную той, которая представлена ​​ниже.

<table>
    <tr>
        <td class="date">2011-01-01</td>
    </tr>
    <tr class="item">
        <td class="headline">Headline</td>
        <td class="link"><a href="#">Link</a></td>
    </tr>
    <tr class="item">
        <td class="headline">Headline</td>
        <td class="link"><a href="#">Link</a></td>
    </tr>
    <tr>
        <td class="date">2011-01-02</td>
    </tr>
    <tr class="item">
        <td class="headline">Headline</td>
        <td class="link"><a href="#">Link</a></td>
    </tr>
    <tr class="item">
        <td class="headline">Headline</td>
        <td class="link"><a href="#">Link</a></td>
    </tr>
</table>

Основная проблема заключается в том, что я просто не могу понять, как 1) отслеживать текущую дату (tr-> td class = "date"), в то время как 2) перебирать элементы в последующем tr: s (tr class = "item" -> td class = "headline" и tr class = "item" -> td class = "link") и 3) сохраняют обработанные данные в массиве.

Кроме того, все данные будут вставлены в базу данных, где каждая запись должна содержать следующую информацию:

  • дата
  • заголовок
  • ссылка

Обратите внимание, что нехватка базы данных не является частью проблемы, я упомянул это только для того, чтобы лучше проиллюстрировать то, что я пытаюсь сделать здесь: -)

Теперь, есть много разных способов снять кожу с кошки. Поэтому, хотя решение данной проблемы действительно приветствуется, я был бы чрезвычайно признателен, если бы кто-то захотел уточнить реальную логику и стратегию, которую вы бы использовали, чтобы «атаковать» такого рода проблемы :-)

И последнее, но не менее важное, извините за такой дурацкий вопрос.

Ответы [ 2 ]

5 голосов
/ 07 января 2011

Основная проблема в том, что эта таблица размечена для внешнего вида, а не для семантической структуры.Правильно выполнено, каждая дата и связанные с ней элементы должны иметь одного родителя.К сожалению, они этого не делают, поэтому нам придется обойтись.

Основная стратегия состоит в том, чтобы перебирать каждую строку в таблице

  • , если в первой таблице данных есть класс 'date ', мы получаем значение даты и обновляем last_seen_date
  • В противном случае мы извлекаем заголовок и ссылку, затем сохраняем (last_seen_date, заголовок, ссылка) в базе данных

import BeautifulSoup

fname = r'c:\mydir\beautifulSoup.html'
soup = BeautifulSoup.BeautifulSoup(open(fname, 'r'))

items = []
last_seen_date = None
for el in soup.findAll('tr'):
    daterow = el.find('td', {'class':'date'})
    if daterow is None:     # not a date - get headline and link
        headline = el.find('td', {'class':'headline'}).text
        link = el.find('a').get('href')
        items.append((last_seen_date, headline, link))
    else:                   # get new date
        last_seen_date = daterow.text
2 голосов
/ 07 января 2011

Вы можете использовать Element Tree, входящий в пакет python.

http://docs.python.org/library/xml.etree.elementtree.html

from xml.etree.ElementTree import ElementTree

tree = ElementTree()
tree.parse('page.xhtml') #This is the XHTML provided in the OP
root = tree.getroot() #Returns the heading "table" element
print(root.tag) #"table"
for eachTableRow in root.getchildren(): 
    #root.getchildren() is a list of all of the <tr> elements
    #So we're going to loop over them and check their attributes
    if 'class' in eachTableRow.attrib:
        #Good to go. Now we know to look for the headline and link
        pass
    else:
        #Okay, so look for the date
        pass

Этого должно быть достаточно, чтобы вы могли приступить к разбору этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...