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



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

由美国宇航局准备

请将意见和建议发送至 xxx.com

日期 时间 年份

年 莫 大 嗯 日 值 1 值 2


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

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

从我所看到的,文件是空格分隔的

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

从网站上读取文件后,我尝试将文件转换为字典,认为我可以将键映射到值,但我无法预测我需要的确切位置。我想一旦我提取我需要的值,我会写文件,然后尝试将字符串转换为双精度或浮点数

我尝试使用

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)

我在堆栈溢出上找到了这个,但我不明白我将如何使用它

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 与我的成像软件交互并触发拍摄图像。

下面是使用正则表达式的简单示例。 这假设您将整个文件读入内存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<

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

为了获取数据,我使用了请求库,而不是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}sw{3}sd{2}sd{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

最新更新