web-dev-qa-db-fra.com

Utiliser les requêtes python pour télécharger le fichier CSV

Voici mon code: 

import csv
import requests
with requests.Session() as s:
    s.post(url, data=payload)
    download = s.get('url that directly download a csv report')

Cela me donne l’accès au fichier csv. J'ai essayé différentes méthodes pour gérer le téléchargement:

Cela donnera le fichier csv en une chaîne:

print download.content

Ceci imprime la première ligne et renvoie l'erreur: _csv.Error: le caractère de nouvelle ligne vu dans un champ sans guillemets

cr = csv.reader(download, dialect=csv.Excel_tab)
for row in cr:
    print row

Ceci imprimera une lettre dans chaque rangée et n'imprimera pas le tout:

cr = csv.reader(download.content, dialect=csv.Excel_tab)
for row in cr:
    print row

Ma question est quelle est la manière la plus efficace de lire un fichier csv dans cette situation. .__ Et comment télécharger le fichier csv actuel.

merci 

19
viviwill

Cela devrait aider:

import csv
import requests

CSV_URL = 'http://samplecsvs.s3.amazonaws.com/Sacramentorealestatetransactions.csv'


with requests.Session() as s:
    download = s.get(CSV_URL)

    decoded_content = download.content.decode('utf-8')

    cr = csv.reader(decoded_content.splitlines(), delimiter=',')
    my_list = list(cr)
    for row in my_list:
        print(row)

Échantillon de sortie:

['street', 'city', 'Zip', 'state', 'beds', 'baths', 'sq__ft', 'type', 'sale_date', 'price', 'latitude', 'longitude']
['3526 HIGH ST', 'SACRAMENTO', '95838', 'CA', '2', '1', '836', 'Residential', 'Wed May 21 00:00:00 EDT 2008', '59222', '38.631913', '-121.434879']
['51 OMAHA CT', 'SACRAMENTO', '95823', 'CA', '3', '1', '1167', 'Residential', 'Wed May 21 00:00:00 EDT 2008', '68212', '38.478902', '-121.431028']
['2796 BRANCH ST', 'SACRAMENTO', '95815', 'CA', '2', '1', '796', 'Residential', 'Wed May 21 00:00:00 EDT 2008', '68880', '38.618305', '-121.443839']
['2805 JANETTE WAY', 'SACRAMENTO', '95815', 'CA', '2', '1', '852', 'Residential', 'Wed May 21 00:00:00 EDT 2008', '69307', '38.616835', '-121.439146']
[...]

Question connexe avec réponse: https://stackoverflow.com/a/33079644/295246


Éditer: d’autres réponses sont utiles si vous devez télécharger des fichiers volumineux (c.-à-d. stream=True).

39
HEADLESS_0NE

Pour simplifier ces réponses et augmenter les performances lors du téléchargement d'un fichier volumineux, les éléments ci-dessous peuvent fonctionner un peu plus efficacement. 

import requests
from contextlib import closing
import csv

url = "http://download-and-process-csv-efficiently/python.csv"

with closing(requests.get(url, stream=True)) as r:
    reader = csv.reader(r.iter_lines(), delimiter=',', quotechar='"')
    for row in reader:
        print row   

En définissant stream=True dans la requête GET, lorsque nous passons r.iter_lines() à csv.reader (), nous transmettons un générateur à csv.reader (). Ce faisant, nous permettons à csv.reader () de parcourir par la suite chaque ligne de la réponse avec for row in reader

Cela évite de charger tout le fichier en mémoire avant le traitement, ce qui réduit considérablement la surcharge de mémoire pour les fichiers volumineux.

14
The Aelfinn

Vous pouvez également utiliser DictReader pour itérer les dictionnaires de {'columnname': 'value', ...}

import csv
import requests

response = requests.get('http://example.test/foo.csv')
reader = csv.DictReader(response.iter_lines())
for record in reader:
    print(record)
6
Antti Haapala

J'aime les réponses de The Aelfinn et aheld . Je ne peux les améliorer qu'en raccourcissant un peu plus, en supprimant les éléments superflus, en utilisant une source de données réelle, en la rendant compatible 2.x et 3.x et en maintenant le niveau élevé d'efficacité de la mémoire observé ailleurs:

import csv
import requests

CSV_URL = 'http://samplecsvs.s3.amazonaws.com/Sacramentorealestatetransactions.csv'

with requests.get(CSV_URL, stream=True) as r:
    lines = (line.decode('utf-8') for line in r.iter_lines())
    for row in csv.reader(lines):
        print(row)

Dommage que 3.x soit moins souple en CSV car l'itérateur doit émettre des chaînes Unicode (alors que requests fait bytes) car la version uniquement 2.x --for row in csv.reader(r.iter_lines()): - est plus pythonique (plus courte et facile à lire). Quoi qu'il en soit, notez que la solution 2.x/3.x ci-dessus ne gérera pas la situation décrite par l'OP dans laquelle une NEWLINE est trouvée non citée dans la lecture des données.

Pour la partie de la question de l'OP concernant le téléchargement (par rapport au traitement) du fichier CSV lui-même, voici un autre script compatible avec that, compatible 2.x et 3.x, minimal, lisible et mémoire. -efficace:

import os
import requests

CSV_URL = 'http://samplecsvs.s3.amazonaws.com/Sacramentorealestatetransactions.csv'

with open(os.path.split(CSV_URL)[1], 'wb') as f, \
        requests.get(CSV_URL, stream=True) as r:
    for line in r.iter_lines():
        f.write(line)
3
wescpy

Si j'ai bien compris, le fichier devrait être ouvert en mode newline universel, ce que vous ne pouvez pas faire directement avec un contenu de réponse (je suppose).

Pour terminer la tâche, vous pouvez soit enregistrer le contenu téléchargé dans un fichier temporaire, soit le traiter en mémoire.

Enregistrer en tant que fichier:

import requests
import csv
import os

temp_file_name = 'temp_csv.csv'
url = 'http://url.to/file.csv'
download = requests.get(url)

with open(temp_file_name, 'w') as temp_file:
    temp_file.writelines(download.content)

with open(temp_file_name, 'rU') as temp_file:
    csv_reader = csv.reader(temp_file, dialect=csv.Excel_tab)
    for line in csv_reader:
        print line

# delete the temp file after process
os.remove(temp_file_name)

En mémoire:

(À mettre à jour)

2
Ares Ou

Vous pouvez mettre à jour la réponse acceptée avec la méthode iter_lines de requêtes si le fichier est très volumineux.

import csv
import requests

CSV_URL = 'http://samplecsvs.s3.amazonaws.com/Sacramentorealestatetransactions.csv'

with requests.Session() as s:
    download = s.get(CSV_URL)

    line_iterator = (x.decode('utf-8') for x in download.iter_lines(decode_unicode=True))

    cr = csv.reader(line_iterator, delimiter=',')
    my_list = list(cr)
    for row in my_list:
        print(row)
1
aheld

L'approche suivante a bien fonctionné pour moi. Je n'ai pas non plus besoin d'utiliser les fonctions csv.reader() ou csv.writer(), ce qui, à mon avis, rend le code plus propre. Le code est compatible avec Python2 et Python 3.

from six.moves import urllib

DOWNLOAD_URL = "https://raw.githubusercontent.com/gjreda/gregreda.com/master/content/notebooks/data/city-of-chicago-salaries.csv"
DOWNLOAD_PATH ="datasets\city-of-chicago-salaries.csv" 
urllib.request.urlretrieve(URL,DOWNLOAD_PATH)

Remarque - six est un paquetage qui aide à l'écriture de code compatible avec Python 2 et Python 3. Pour plus d'informations sur six, voir - Que fait from six.moves import urllib en Python?

0
aamir23