【问题标题】:Parsing CSV to chart stock ticker data解析 CSV 以绘制股票代码数据
【发布时间】:2016-05-30 06:43:10
【问题描述】:

我创建了一个程序,它获取股票代码,爬取网络以查找每个代码的历史价格的 CSV,并使用 matplotlib 绘制它们。几乎一切正常,但我在解析 CSV 以分离出每个价格时遇到了问题。

我得到的错误是:

prices = [float(row[4]) for row in csv_rows]

IndexError: 列表索引超出范围

我知道问题出在哪里,我只是不确定我应该如何解决它。

(问题出在parseCSV() 方法中)

# Loop to chart multiple stocks
def chartStocks(*tickers):
    for ticker in tickers:
        chartStock(ticker)
        
# Single chart stock method
def chartStock(ticker):
    url = "http://finance.yahoo.com/q/hp?s=" + str(ticker) + "+Historical+Prices"
    sourceCode = requests.get(url)
    plainText = sourceCode.text
    soup = BeautifulSoup(plainText, "html.parser")
    csv = findCSV(soup)
    parseCSV(csv)

# Find the CSV URL        
def findCSV(soupPage):
    CSV_URL_PREFIX = 'http://real-chart.finance.yahoo.com/table.csv?s='
    links = soupPage.findAll('a')
    for link in links:
        href = link.get('href', '')
        if href.startswith(CSV_URL_PREFIX):
            return href
    
# Parse CSV for daily prices
def parseCSV(csv_text):
    csv_rows = csv.reader(csv_text.split('\n'))

    prices = [float(row[4]) for row in csv_rows]
    days = list(range(len(prices)))
    point = collections.namedtuple('Point', ['x', 'y'])

    for price in prices:
        i = 0
        p = point(days[i], prices[i])
        points = []
        points.append(p)
    print(points)

    plotStock(points)

# Plot the data
def plotStock(points):
    plt.plot(points)
    plt.show()

【问题讨论】:

  • 一旦您使用@mhawke 的答案实际下载 csv 数据并使用@Alexander 的方法来处理少于 5 个项目的行,那么您还需要将 points = [] 移出 forparseCSV() 结尾附近循环。
  • 询问的问题(在处理 CSV 数据时处理 IndexError)似乎与 this earlier question 重复(或者可能是 this onethis one) .当然,正如其他几个人已经指出的那样,您认为的问题实际上是代码中最少的问题。
  • 我相信这个帖子是under discussion on meta

标签: python parsing csv


【解决方案1】:

问题在于parseCSV() 需要一个包含 CSV 数据的字符串,但实际上传递的是 CSV 数据的 URL,而不是下载的 CSV 数据。

这是因为 findCSV(soup) 为页面上找到的 CSV 链接返回 href 的值,然后将该值传递给 parseCSV()。 CSV 阅读器会找到一行未定界的数据,因此只有一列,而不是预期的 >4。

CSV 数据从未真正被下载。

你可以这样写parseCSV() 的前几行:

def parseCSV(csv_url):
    r = requests.get(csv_url) 
    csv_rows = csv.reader(r.iter_lines())

【讨论】:

  • ..在 OP 完成所有操作后,他们会看到数据行看起来像表 here 中显示的那样 - 所以他们用于解析和绘制数据的其余代码也不行。
  • @martineau:实际上,在添加了另一个答案中建议的行长度检查之后,我认为 OP 根本不会看到任何东西 - 只是一个空列表的图。
  • 我决定忘记 CSV 模块,自己解析它。现在工作正常:)
  • @123:所以你现在正在下载 CSV 数据?
  • @123:哦,我明白了……数据完整吗?底部有分页链接,点击“next”给出下一页结果。
【解决方案2】:

您需要检查您的行是否至少有五个元素(即索引位置 4)。

prices = [float(row[4]) for row in csv_rows if len(row) > 4]

【讨论】:

  • 。这是 csv 文件中包含一些额外空行的常见问题。您可能认为 csv 解析器会跳过这些行,但事实并非如此。
  • 这不是问题。 CSV 资源的 URL 正在传递给 parseCSV()。永远不会检索到实际的 CSV 数据。
猜你喜欢
  • 1970-01-01
  • 2011-01-23
  • 2013-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多