解析具有大量标题信息的混合文本文件

时间:2019-03-31 23:23:09

标签: python

我是一名业余天文学家(已退休),只是想着一个主意。我想从作为文本文件的NASA网站上抓取数据,并提取特定值以帮助我确定何时进行观察。文本文件每60秒自动更新一次。文本文件在需要处理的实际数据行和数据列之前具有一些标题信息。实际数据是数字。示例:

由NASA准备

请向xxx.com发送评论和建议

日期时间年份

yr mo da hhmm日value1 value2


2019 03 31 1933 234 6.00e-09 1.00e-09

我想访问字符串数字数据并将其转换为双精度

从我可以看到文件是用空格分隔的

我想每60秒对网站进行一次轮询,如果值1和值2高于特定阈值,这将触发PyAutoGUI自动化软件应用程序以拍摄图像。

从网站上读取文件后,我尝试将文件转换为字典,以为可以将键映射到值,但是我无法预测所需的确切位置。我以为一旦提取了所需的值,我就会写文件,然后尝试将字符串转换为double或float

我尝试使用

import re
re.split

读取每一行并拆分信息,但是由于标题信息,我感到非常混乱

我想使用一种简单的方法来打开文件,这行得通


import urllib
import csv

data = urllib.urlopen("https://services.swpc.noaa.gov/text/goes-xray-flux-primary.txt").read()

print (data)

我是在Stack溢出时发现的,但我不知道该如何使用

file = open('abc.txt','r')
while 1:
    a = file.readline()
    if a =='': break
    a = a.split()                  #This creates a list of the input
    name = a[0]
    value = int(a[1])              # or value=float(a[1]) whatever you want
    #use the name and value howsoever
f.close()

我想要提取的值1和值2比第二部分(我还没有开始)提取为两倍或浮点数(我尚未开始),我将比较值1和值2,如果它们大约是特定阈值,会触发PyAutoGUI与我的成像软件进行交互并触发拍摄图像。

2 个答案:

答案 0 :(得分:4)

这是使用正则表达式的简单示例。假设您只用一个f.read()就将整个文件读入内存,而不是费力地处理带有正则表达式的单行,这通常是更简单的方法(而且我很懒,并且不想必须创建一个测试文件):

import re

data = """
blah
blah

yr mo da hhmm day value1 value2

2019 03 31 1933 234 6.00e-09 1.00e-09

blah
"""

pattern = re.compile(r"(\d+) (\d+) (\d+) (\d+) (\d+) ([^\s]+) ([^\s]+)")

def main():
    m = pattern.search(data)
    if m:
        # Do whatever processing you want to do here.  You have access to all 7 input
        # fields via m.group(1-7)
        d1 = float(m.group(6))
        d2 = float(m.group(7))
        print(">{}< >{}<".format(d1, d2))
    else:
        print("no match")

main()

输出:

>6e-09< >1e-09<

如果我对输入数据做出了错误的假设,那么您可能需要对此进行一些调整,但这仍然为您提供了总体思路。

这应该处理输入中存在的任何其他内容,只要没有其他事情看起来像您感兴趣的那一行。

更新:

我不能一个人好好离开。这是从您提供的URL中提取数据并处理所有匹配行的代码:

import re
import urllib

pattern = re.compile(r"(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+([^\s]+)\s+([^\s]+)")

def main():

    data = urllib.urlopen("https://services.swpc.noaa.gov/text/goes-xray-flux-primary.txt").read()

    pos = 0
    while True:
        m = pattern.search(data, pos)
        if not m:
            break
        pos = m.end()
        # Do whatever processing you want to do here.  You have access to all 8 input
        # fields via m.group(1-8)
        f1 = float(m.group(7))
        f2 = float(m.group(8))
        print(">{}< >{}<".format(f1, f2))

main()

结果:

>9.22e-09< >1e-09<
>1.06e-08< >1e-09<
...
>8.99e-09< >1e-09<
>1.01e-08< >1e-09<

答案 1 :(得分:1)

这是一个有趣的小挑战,我已经为您从表中提取了所有数据,将其映射到类,并将数据适当地转换为intDecimal。填充后,您可以从中读取所需的所有数据。

要获取数据,我使用了请求库,而不是urllib,这只是个人喜好。如果您也想使用pip install requests,则可以使用。它具有iter_lines方法,可以遍历数据行。

这可能对您需要的东西来说太过分了,但是无论如何我写它时,我都认为应该为您发布。

import re
from datetime import datetime
from decimal import Decimal

import requests


class SolarXrayFluxData:
    def __init__(
            self,
            year,
            month,
            day,
            time,
            modified_julian_day,
            seconds_of_the_day,
            short,
            long
    ):
        self.date = datetime(
            int(year), int(month), int(day), hour=int(time[:2]), minute=int(time[2:])
        )
        self.modified_julian_day = int(modified_julian_day)
        self.seconds_of_the_day = int(seconds_of_the_day)
        self.short = Decimal(short)
        self.long = Decimal(long)


class GoesXrayFluxPrimary:
    def __init__(self):
        self.created_at = ''
        self.data = []

    def extract_data(self, url):
        data = requests.get(url)
        for i, line in enumerate(data.iter_lines(decode_unicode=True)):
            if line[0] in [':', '#']:
                if i is 1:
                    self.set_created_at(line)
                continue

            row_data = re.findall(r"(\S+)", line)
            self.data.append(SolarXrayFluxData(*row_data))

    def set_created_at(self, line):
        date_str = re.search(r'\d{4}\s\w{3}\s\d{2}\s\d{4}', line).group(0)
        self.created_at = datetime.strptime(date_str, '%Y %b %d %H%M')


if __name__ == '__main__':
    goes_xray_flux_primary = GoesXrayFluxPrimary()
    goes_xray_flux_primary.extract_data('https://services.swpc.noaa.gov/text/goes-xray-flux-primary.txt')
    print("Created At: %s" % goes_xray_flux_primary.created_at)
    for row in goes_xray_flux_primary.data:
        print(row.date)
        print("%.12f, %.12f" % (row.short, row.long))


SolarXrayFluxData类的目的是存储每个项目数据,并确保其使用的格式正确。使用GoesXrayFluxPrimary类时,将填充SolarXrayFluxData的列表并存储您可能要提取的任何其他数据。例如,我已经获取了Created的日期和时间。您还可以从标头数据中获取LocationSource