Я использую Python 3.5 на Windows.

У меня есть небольшой фрагмент кода, который загружает около ста CSV-файлов с разных URL-адресов, которые хранятся в Links.txt:

from urllib import request

new_lines = 'None'


def download_data(csv_url):
    response = request.urlopen(csv_url)
    csv = response.read()
    csv_str = str(csv)
    global new_lines
    new_lines = csv_str.split("\\n")

with open('Links.txt') as file:
    for line in file:
        URL = line
        file_name = URL[54:].rsplit('.ST', 1)[0]
        download_data(URL)
        save_destination = 'C:\\Download data\\Data\\' + file_name + '.csv'
        fx = open(save_destination, "w")
        for lines in new_lines:
            fx.write(lines+"\n")
        fx.close()

Проблема в том, что сгенерированные CSV-файлы всегда начинаются с b ', а после последней строки данных следует еще один ' и пара пустых строк для завершения. Я не вижу этих символов, когда смотрю на файлы из браузера (перед тем, как загрузить их).

Это создает проблемы, когда я хочу импортировать и использовать данные в базе данных. Есть ли у вас какие-либо идеи о том, почему это происходит и как я могу получить код для правильной записи файлов CSV?

Советы, которые могут сделать код быстрее / лучше, или корректировки для других недостатков в коде, очевидно, очень приветствуются.

2
user5683764 16 Дек 2015 в 00:34

3 ответа

Лучший ответ

Происходит следующее: urllib обрабатывает свой поток как байты - любая строка, которая выглядит как b'...', означает, что это строка байтов.

Ваша непосредственная проблема может быть решена путем кодирования потока путем вызова decode('utf-8') (как показывает Chedy2149), который преобразует байты данных.

Однако вы можете решить эту проблему, загрузив файл прямо на диск. Вы проходите работу по загрузке, разделению и записи на диск, но все это кажется ненужным, потому что ваш код просто в конечном итоге записывает содержимое файла на диск без дополнительной работы с ними.

Вы можете использовать urllib.request.urlretrieve и скачать в файл напрямую.

Вот пример, модифицированный из вашего кода.

import urllib.request

def download_data(url, file_to_save):
    filename, rsp = urllib.request.urlretrieve(url, file_to_save)
    # Assuming everything worked, the file has been downloaded to file_to_save

with open('Links.txt') as file:
    for line in file:
        url = line.rstrip() # adding this here to remove extraneous '\n' from string
        file_name = url[54:].rsplit('.ST', 1)[0]
        save_destination = 'C:\\Download data\\Data\\' + file_name + '.csv'
        download_data(url, save_destination)
1
wkl 15 Дек 2015 в 22:29

Проблема в том, что ваша функция возвращает объект bytes; str() не преобразует его в строку так, как вы ожидаете. Используйте csv_str = csv.decode() вместо этого.

0
alexis 15 Дек 2015 в 22:08

В функции download_data необходимо преобразовать ответ csv байтовой строки в простую строку.
Попробуйте заменить csv_str = str(csv) на csv_str = csv.decode('utf-8').

Это должно правильно декодировать строку байтов, возвращаемую response.read().

1
Chedy2149 15 Дек 2015 в 22:04