stackoverflow上的第一篇文章,以及python的新手。我正在尝试从wunderground的某个位置读取天气数据。它应该是直截了当的:
import csv
import urllib2
url = 'http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=KMDLAURE4&day=9&month=6&year=2013&graphspan=day&format=1'
response = urllib2.urlopen(url)
cr = csv.reader(response)
然而,当我这样做时,我在所有数据之间得到了额外的一行。因此,如果我检查.csv输出的前几行,我会得到以下结果:
cr.next()
Out[210]: []
cr.next()
Out[211]:
['Time',
blah blah blah fields redacted
'DateUTC<br>']
cr.next()
Out[212]:
['2013-06-09 00:07:00',
blah blah blah data redacted
'2013-06-09 04:07:00',
'']
cr.next()
Out[213]: ['<br>']
cr.next()
Out[214]:
['2013-06-09 00:22:00',
blah blah blah data redacted,
'2013-06-09 04:22:00',
'']
我可以循环遍历文件,扔掉所有其他行,或检查该行是否只包含&lt; br&gt;并摆脱它。对我来说,这是一个不优雅的解决方案,因为真正的“问题”是由于阅读文本。这似乎是“打开二进制”或编解码器问题,但我该如何检查?谢谢!
答案 0 :(得分:1)
必须有办法告诉wunderground返回真正的CSV格式,而不是HTML。但是,您可以通过跳过那些太短的行来解决它:
import csv
import urllib2
url = 'http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=KMDLAURE4&day=9&month=6&year=2013&graphspan=day&format=1'
response = urllib2.urlopen(url)
cr = csv.reader(response)
for row in cr:
if len(row) <= 1: continue
print row
这是一种不同的方法:创建一个类来过滤掉那些不需要的行:
import csv
import urllib2
class RemoveBlank(object):
def __init__(self, response):
self.response = response
def __iter__(self):
return self
def next(self):
line = '\n'
while line == '\n' or line == '<br>\n':
line = next(self.response)
return line
url = 'http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=KMDLAURE4&day=9&month=6&year=2013&graphspan=day&format=1'
response = urllib2.urlopen(url)
cr = csv.reader(RemoveBlank(response))
for row in cr:
print row
这次,不是将响应对象提供给cdv.reader
,而是将该响应对象包装在RemoveBlank
对象中。请注意,在Python 3中,该方法应命名为__next__
。
这种方法的优点是:它使主体保持清洁,因此您可以专注于逻辑。
答案 1 :(得分:0)
首先,这不是您问题的答案。这是使用不同方法解决问题的替代解决方案。
我使用相同的API,获得相同信息的更好方法是使用Larry Lustig评论的JSON响应。
from json import loads
from urllib import urlopen
url = 'http://api.wunderground.com/api/01f4106be8822ff4/history_201300609/q/MD/Laurel.json'
response = loads(urlopen(url).read())
print 'Date', 'Temperature', 'Dew Point', 'Umidity'
for w in response['history']['observations']:
print w['date']['pretty'], w['tempi'], w['dewpti'], w['hum']
响应
Date Temperature Dew Point Umidity
12:15 AM EST on January 29, 2013 32.0 32.0 100
12:36 AM EST on January 29, 2013 32.0 32.0 100
12:57 AM EST on January 29, 2013 32.0 32.0 100
1:18 AM EST on January 29, 2013 32.0 32.0 100
1:39 AM EST on January 29, 2013 32.0 32.0 100
在官方API doc中,您可以找到更多信息。
在这里,您的问题的解决方案。这是一种将CSV文件作为字典读取的方法。
from urllib import urlopen
from csv import DictReader
from StrinIO import StringIO
url = 'http://api.wunderground.com/api/01f4106be8822ff4/history_201300609/q/MD/Laurel.json'
response = StringIO(urlopen(url).read())
weather = DictReader(response)
# Skips header
weather.next()
for w in weather:
print w
响应
{None: ['2013-06-09 00:07:00', '18.5', '17.2', '1015.8', 'WNW', '285', '0.0', '-1607.4', '92', '-2539.7', '', '', '0.0', 'weatherlink.com 1.10', '2013-06-09 04:07:00', '']}
{None: ['<br>']}
{None: ['2013-06-09 00:22:00', '18.6', '17.8', '1015.8', 'WNW', '285', '0.0', '-1607.4', '93', '-2539.7', '', '', '0.0', 'weatherlink.com 1.10', '2013-06-09 04:22:00', '']}
再次,你的结果是dict。更容易处理。