【问题标题】:Reading .csv data from URL in python: extra lines从 python 中的 URL 读取 .csv 数据:额外的行
【发布时间】:2014-07-30 15:41:09
【问题描述】:

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;,那么它是 HTML 文件而不是(正确的)CSV 文件。
  • 这种很烂。我查看了网站。看起来它正在返回 csv 数据,但内容类型错误,这就是您在打开 url 时获得格式 (
    ) 等的原因。看起来你只需要遍历你的数据并忽略/远程导致问题的标签。
  • 这似乎不是一个神奇的 API 调用,在这里讨论:wunderground.com/weather/api。该 API 返回 XML 或 JSON,但不返回 CSV。
  • 对。我试图避免使用 API,因为(对我而言)这似乎更适合于获取实时预测数据。

标签: python url csv codec


【解决方案1】:

首先,这不是您问题的答案。这是使用不同方式解决问题的替代解决方案。

我使用相同的 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 的形式出现。更容易处理。

【讨论】:

  • 我喜欢你对 API 的使用。谢谢!如果我现在不使用它,我最终会使用它。但是,当我运行代码的顶部时,它在“print w”语句上失败,并出现错误“TypeError:字符串索引必须是整数”
【解决方案2】:

必须有办法告诉 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__

这种方法的优点:它使主体保持干净,因此您可以专注于逻辑。

【讨论】:

  • 太棒了。这就像一个魅力。我了解课程的最后一部分,也就是说,当该行为空白或仅包含
    \n 时,您将该行设置为等于下一行(可能已填充)。将 removeblank 设为类而不是仅定义函数的原因是什么?
  • 我需要一个类来保存响应对象。
猜你喜欢
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 2021-03-26
  • 2017-05-19
  • 1970-01-01
  • 2013-09-06
  • 2016-09-29
  • 1970-01-01
相关资源
最近更新 更多