【问题标题】:Find first specific HTML tag above the found selection - Python / BeautifulSoup在找到的选择上方找到第一个特定的 HTML 标记 - Python / BeautifulSoup
【发布时间】:2018-02-28 20:59:40
【问题描述】:

我有一个以下格式的事件表

<table class="events">
<tbody>
    <tr>
        <td"><span class="event_date">28.02.2018</span></td>
    </tr>
    <tr class="event">
        <td class="event_time">18:00</td>
        <td class="event_name">Event_1</td>
    </tr>
    <tr class="event">
        <td class="event_time">19:00</td>
        <td class="event_name">Event_2</td>
    </tr>
    <tr>
        <td"><span class="event_date">01.03.2018</span></td>
    </tr>
    <tr class="event">
        <td class="event_time">18:00</td>
        <td class="event_name">Event_3</td>
    </tr>
    <tr class="event">
        <td class="event_time">19:00</td>
        <td class="event_name">Event_4</td>
    </tr>
    <tr class="event">
        <td class="event_time">20:00</td>
        <td class="event_name">Event_5</td>
    </tr>
</tbody>

我可以使用以下命令轻松提取每个事件的时间和名称

event_container = page_soup.findAll("tr", {"class":"event"})

for event in event_container:
    event_name = event.find("td", {"class":"event_name"})
    event_time = event.find("td", {"class":"event_time"})

但是我无法将 event_date 正确分配给这些事件

想要的输出

名称:Event_1,日期:28.02.2018,时间:18:00

名称:Event_2,日期:28.02.2018,时间:19:00

名称:Event_3,日期:01.03.2018,时间:18:00

名称:Event_4,日期:01.03.2018,时间:19:00

名称:Event_5,日期:01.03.2018,时间:20:00

感谢您的帮助

【问题讨论】:

    标签: python beautifulsoup html-parsing


    【解决方案1】:

    您可以做的一件事是遍历所有&lt;tr&gt; 标签并检查它是否有带有日期的&lt;span&gt; 标签。如果有日期,则更新日期,否则获取名称和时间。

    但在 Python 中,它是EAFP(请求宽恕比请求许可更容易)。所以,你可以简单地使用这个:

    table = soup.find('table', class_='events')
    event_date = ''
    for row in table.find_all('tr'):
        try:
            event_date = row.td.span.text
            continue
        except AttributeError:
            pass
        event_name = row.find('td', class_='event_name').text
        event_time = row.find('td', class_='event_time').text
        print('Name: {}, Date: {}, Time: {}'.format(event_name, event_date, event_time))
    

    输出:

    Name: Event_1, Date: 28.02.2018, Time: 18:00
    Name: Event_2, Date: 28.02.2018, Time: 19:00
    Name: Event_3, Date: 01.03.2018, Time: 18:00
    Name: Event_4, Date: 01.03.2018, Time: 19:00
    Name: Event_5, Date: 01.03.2018, Time: 20:00
    

    【讨论】:

    • 谢谢 - 这是我正在寻找的解决方案!只是我自己无法弄清楚 for 循环。
    【解决方案2】:

    一种可能是抓取所有需要的文本,然后在适当的事件日期下分组:

    from bs4 import BeautifulSoup as soup
    import itertools, re
    def beautify(f):
       def wrapper():
          return ["Name: {name}, Date: {date}, Time: {time}".format(**dict(zip(['date', 'time', 'name'], i))) for i in f()]
       return wrapper
    
    @beautify
    def raw_data():
       s = soup(data, 'lxml')
       final_data = [i.text for i in s.find_all('td')]
       final_results = [list(b) for a, b in itertools.groupby(final_data, key=lambda x:bool(re.findall('\d+\.\d+\.\d+$', x)))]
       new_final_data = [[a+b[i:i+2] for i in range(0, len(b), 2)] for a, b in [final_results[i:i+2] for i in range(0, len(final_results), 2)]]
       return [i for b in new_final_data for i in b]
    

    输出:

    ['Name: Event_1, Date: 28.02.2018, Time: 18:00', 'Name: Event_2, Date: 28.02.2018, Time: 19:00', 'Name: Event_3, Date: 01.03.2018, Time: 18:00', 'Name: Event_4, Date: 01.03.2018, Time: 19:00', 'Name: Event_5, Date: 01.03.2018, Time: 20:00']
    

    【讨论】:

      猜你喜欢
      • 2017-11-15
      • 1970-01-01
      • 2014-11-11
      • 2020-10-05
      • 1970-01-01
      • 2016-08-22
      • 2011-02-01
      • 2013-08-28
      • 1970-01-01
      相关资源
      最近更新 更多