我是一名业余天文学家(已退休),只是想着一个主意。我想从作为文本文件的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与我的成像软件进行交互并触发拍摄图像。
答案 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)
这是一个有趣的小挑战,我已经为您从表中提取了所有数据,将其映射到类,并将数据适当地转换为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}\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
的日期和时间。您还可以从标头数据中获取Location
和Source
。