0

我正在尝试从 Echonest API 中提取一百首不同歌曲的歌曲数据。我在 CSV 文件中有每首歌曲的 ID - 我正在尝试编写一个脚本来读取 ID,将它们附加到 API url,并将数据写入新的 CSV,但我遇到了一点麻烦。

有没有一种好方法可以循环提取 ID 代码并将它们附加到 URL 中?这就是我到目前为止所拥有的;不确定如何/在何处将其放在有关将 ID 添加到 URL 的部分中。

import urllib2
import json
import csv
from time import sleep
outfile_path='/Users/path/to/file.csv'
api_url = 'http://developer.echonest.com/api/v4/song/profile?'
API_KEY = ''
writer = csv.writer(open(outfile_path))
with open('/Users/path/to/file.csv') as f:
    for row in csv.DictReader(f):
        song_id = row['id']
        qs = urllib.urlencode({"api_key": API_KEY,
                               "bucket": "audio_summary",
                               "id": song_id})
        url = '{}?{}'.format(API_URL, qs)
        parsed_json = json.load(resource)
        for song in parsed_json['results']:
          row = []
          writer.writerow({k: v.encode('utf-8') for k, v in song.items()})
          sleep(5)
4

1 回答 1

1

我不确定你被困在哪一部分(你发布的代码有很多问题会阻止它甚至编译,更不用说解决你的真正问题了,而且你还没有描述问题),但是似乎有两个可能的地方。

首先,我不确定您是否知道如何打开 CSV 文件并从中获取值。您正在尝试打开一个目录而不是一个文件,并且您没有对行做任何事情,然后当我 99% 确定时,您尝试为 100 行中的每一行执行 100 次内部循环您只想为 100 行中的每一行执行一次。

如果使用csv.reader,则必须知道 ID 所在的列号;使用 a 会容易得多csv.DictReader,因为您只需要知道该列的名称是什么。所以,让我们这样做:

with open('/path/to/inputfile.csv') as f:
    for row in csv.DictReader(f):
        song_id = row['id']
        # make and process request with song_id

如果您的 CSV 文件没有标题行,则只需使用reader, 并将列号(例如,0第一列)代替'id'.


现在,您要对该 ID 执行的操作是将每个 ID 粘贴到 URL 中。您可以通过使用字符串格式来做到这一点。例如:

URL_TEMPLATE = 'http://developer.echonest.com/api/v4/song/profile?api_key=&bucket=audio_summary&id={}'

# ... inside the for loop ...
song_id = row['id']
url = URL_TEMPLATE.format(song_id)
resource = urllib2.urlopen(url)
parsed_json = json.load(resource)

您还需要填写您的api_key,否则 EchoNest 不会接受您的查询,因此:

URL_TEMPLATE = 'http://developer.echonest.com/api/v4/song/profile?api_key={}&bucket=audio_summary&id={}'
API_KEY = "<your API key goes here>"

# ... inside the for loop ...
url = URL_TEMPLATE.format(API_KEY, song_id)

但是,通常最好使用urlencode生成查询字符串,而不是尝试通过字符串方法来完成。除了更具可读性之外,它还将处理您可能甚至没有想到的事情,例如在您的值中编码任何对 URL 不友好的字符。所以:

API_URL = 'http://developer.echonest.com/api/v4/song/profile'

# ... inside the for loop ...
qs = urllib.urlencode({"api_key": API_KEY, 
                       "bucket": "audio_summary",
                       "id": song_id})
url = '{}?{}'.format(API_URL, qs)

然后你只需要循环parsed_join['results']并写出你已经写好的行的部分。但有两个注意事项。

第一,str(foo.encode('utf-8'))是不必要的;encode已经返回一个str.

其次,你有很多不必要的重复代码来构建它row。你对song字典中的每个键都做同样的事情,所以为什么不只使用 aDictWriter并将其保留为字典:

writer.writerow({k: v.encode('utf-8') for k, v in song.items()})

…或者,如果您更喜欢使用writer,只需使用operator.itemgetter一次将它们全部提取到列表中:

writer.writerow(v.encode('utf-8') for v in itemgetter(headers)(song))
于 2013-09-10T21:28:39.550 回答