【问题标题】:Multiple-line output from a single-line match in PythonPython中单行匹配的多行输出
【发布时间】:2023-03-26 21:45:01
【问题描述】:

我仍然是 Python 的新手,但我正在尝试编写代码来解析来自 NOAA 的天气并按照我们的无线电广播的顺序显示它。

我已经设法整理了一个使用 python 表达式的当前条件列表,其中 html 文件被分割成行列表,然后以正确的顺序重新输出,但每个都是一个行数据。该代码如下所示:

#other function downloads  
#http://www.arh.noaa.gov/wmofcst_pf.php?wmo=ASAK48PAFC&type=public
#and renames it currents.html
from bs4 import BeautifulSoup as bs
import re
soup = bs(open('currents.html')
weatherRaw = soup.pre.string
towns = ['PAOM', 'PAUN', 'PAGM', 'PASA']
townOut = []
weatherLines = weatherRaw.splitlines()
for i in range(len(towns)):
    p = re.compile(towns[i] + '.*')
    for line in weatherLines:
        matched = p.match(line)
        if matched:
            townOut.append(matched.group())

现在我正在处理预测部分,我遇到了一个问题,因为每个预测都必须跨越多行,并且我已将文件切割成行列表。

所以:我正在寻找的是一个允许我使用类似循环的表达式,这次从找到的行开始追加并在仅包含 && 的行结束。像这样的:

#sample data from http://www.arh.noaa.gov/wmofcst.php?wmo=FPAK52PAFG&type=public
#BeautifulSouped into list fcst (forecast.pre.get_text().splitlines())
zones = ['AKZ214', 'AKZ215', 'AKZ213'] #note the out-of-numerical-order zones
weatherFull = []
for i in range(len(zones)):
    start = re.compile(zones[i] '.*')
    end = re.compile('&&')
    for line in fcst:
        matched = start.match(line)
        if matched:
            weatherFull.append(matched.group())
            #and the other lines of various contents and length
            #until reaching the end match object

我应该如何改进这段代码?我知道这很冗长,但是当我开始的时候,我喜欢能够跟踪我在做什么。提前致谢!

【问题讨论】:

    标签: python list beautifulsoup weather


    【解决方案1】:

    抱歉,如果这不是您所追求的(在这种情况下,很乐意调整)。您使用 BeautifulSoup 真是太棒了,但您实际上可以更进一步。查看 HTML,似乎每个块都以 <a name=zone> 结构开始,并在下一个 <a name=zone> 结束。在这种情况下,您可以执行以下操作来为每个区域拉取相应的 HTML:

    from bs4 import BeautifulSoup
    
    # I put the HTML in a file, but this will work with a URL as well
    with open('weather.html', 'r') as f:
      fcst = f.read()
    
    # Turn the html into a navigable soup object
    soup = BeautifulSoup(fcst)
    
    # Define your zones
    zones = ['AKZ214', 'AKZ215', 'AKZ213']
    
    weatherFull = []
    
    # This is a more Pythonic loop structure - instead of looping over
    # a range of len(zones), simply iterate over each element itself
    for zone in zones:
      # Here we use BS's built-in 'find' function to find the 'a' element
      # with a name = the zone in question (as this is the pattern).
      zone_node = soup.find('a', {'name': zone})
    
      # This loop will continue to cycle through the elements after the 'a'
      # tag until it hits another 'a' (this is highly structure dependent :) )
      while True:
        weatherFull.append(zone_node)
        # Set the tag node = to the next node
        zone_node = zone_node.nextSibling
        # If the next node's tag name = 'a', break out and go to the next zone
        if getattr(zone_node, 'name', None)  == 'a':
          break
    
    # Process weatherFull however you like
    print weatherFull
    

    希望这会有所帮助(或者至少在您想要的范围内!)。

    【讨论】:

    • 这正是我一直在寻找的——当我在第一组中不能以这种方式使用 BeautifulSoup 时我很沮丧(因为该 html 集中没有标签)。我不敢相信这次我忘了检查它是否被标记了!谢谢您的帮助。 :)
    • @Raveler1 完全不用担心!有一篇关于使用正则表达式解析 HTML 的非常有趣的帖子,您可能已经看过了(stackoverflow.com/questions/1732348/…,以防万一)——这肯定让我远离了正则表达式,转而使用 BS 之类的东西 :) 另外,因为您的代码在 Python 方面非常新看起来很棒!
    • 谢谢夸奖;几天来我一直在研究这个问题,而且我是干净、可读的代码的粉丝。我的许多搜索都显示缺乏可读的代码......我很高兴我是一名无线电广播员而不是编码员。不过,拥有解决问题的工具集真是太好了!自从在大学学习 BASIC、C++ 和一点点 Java 之后,我就没有使用过编码语言。语言有其怪癖很酷,但通常会运行类似的过程。那篇关于解析 HTML 的帖子很棒。我不知道是好是坏,我觉得这很有趣……;-)
    • @Raveler1 你会喜欢 Python 的 :) 在我看来,它需要特定缩进的事实使得语言更具可读性。那篇文章每次都让我发笑,尤其是你开始处理 HTML 的次数越多,对使用真正解析器以外的其他东西时感到恶心:)
    猜你喜欢
    • 1970-01-01
    • 2021-12-01
    • 2011-02-12
    • 2018-01-28
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    相关资源
    最近更新 更多