BeautifulSoup, чтобы очистить детали с удаленного сайта для отображения на локальном сайте - PullRequest
0 голосов
/ 28 февраля 2011

новичок в Python и BeautifulSoup, я пытаюсь собрать информацию о гонке с веб-сайта для отображения на веб-сайте моего местного клуба.

Вот мой код:

import urllib2
import sys
import os

sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
from BeautifulSoup import BeautifulSoup

# Road
#cyclelab_url='http://www.cyclelab.com/OnLine%20Entries.aspx?type=Road%20Events'

# MTB
cyclelab_url='http://www.cyclelab.com/OnLine%20Entries.aspx?type=Mountain%20Biking%20Events'

response = urllib2.urlopen(cyclelab_url)
html = response.read()

soup = BeautifulSoup(html)
event_names = soup.findAll(attrs= {"class" : "SpanEventName"})
for event in event_names:
    txt = event.find(text=True)
    print txt

event_details = soup.findAll(attrs= {"class" : "TDText"})
for detail in event_details:
    lines=[]
    txt_details = detail.find(text=True)
    print txt_details

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

Ответы [ 2 ]

4 голосов
/ 28 февраля 2011

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

soup = BeautifulSoup(html)
event_names = soup.findAll(attrs= {"class" : "SpanEventName"})
for event in event_names:
    txt = event.find(text=True)
    print "Event name: "+txt.strip()
    # Find each parent in turn until we find the table that encloses
    # the event details:
    parent = event.parent
    while parent and parent.name != "table":
        parent = parent.parent
    if not parent:
        raise Exception, "Failed to find a <table> enclosing the event"
    # Now parent is the table element, so look for every
    # row under that table, and then the cells under that:
    for row in parent.findAll('tr'):
        cells = row.findAll('td')
        # We only care about the rows where there is a multiple of two
        # cells, since these are the key / value pairs:
        if len(cells) % 2 != 0:
            continue
        for i in xrange(0,len(cells),2):
            key_text = cells[i].find(text=True)
            value_text = cells[i+1].find(text=True)
            if key_text and value_text:
                print "  Key:",key_text.strip()
                print "  Value:",value_text.strip()

Вывод выглядит так:

Event name: Columbia Grape Escape 2011
  Key: Category:
  Value: Mountain Biking Events
  Key: Event Date:
  Value: 4 March 2011 to 6 March 2011
  Key: Entries Close:
  Value: 31 January 2011 at 23:00
  Key: Venue:
  Value: Eden on the Bay, Blouberg
  Key: Province:
  Value: Western Cape
  Key: Distance:
  Value: 3 Day, 3 Stage Race (228km)
  Key: Starting Time:
  Value: -1:-1
  Key: Timed By:
  Value: RaceTec
Event name: Investpro MTB Race 2011
  Key: Category:
  Value: Mountain Biking Events
  Key: Event Date:
  Value: 5 March 2011
  Key: Entries Close:
  Value: 25 February 2011 at 23:00

... и т. Д.

0 голосов
/ 28 февраля 2011

Обновление: Марк Лонгэйр имеет правильный / лучший ответ.См. Комментарии.

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

[....]
event_names = soup.findAll(attrs= {"class" : "SpanEventName"})
event_details = soup.findAll(attrs= {"class" : "TDText"})
for event in event_names:
       txt = event.find(text=True)
       print txt
    for detail in event_details:
        txt_details = detail.find(text=True)
        print txt_details

Некоторые дальнейшие улучшения: Вы можете удалить все пробелы и символы новой строки с помощью .strip ().Например: text_details = detail.find(text=True).strip().

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