web-dev-qa-db-ja.com

pythonリクエストを使用してCSVをダウンロードします

ここに私のコードがあります:

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

これにより、csvファイルにアクセスできます。ダウンロードに対処するために別の方法を試しました:

これにより、csvファイルが1つの文字列になります。

print download.content

これにより、最初の行が出力され、エラーが返されます:_csv.Error:引用符で囲まれていないフィールドに改行文字が表示されます

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

これにより、各行に文字が印刷され、全体が印刷されません。

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

私の質問は、この状況でcsvファイルを読み取る最も効率的な方法は何ですか。そして、それをダウンロードする方法。

ありがとう

32
viviwill

これは役立つはずです:

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)

出力サンプル:

['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']
[...]

関連する質問と回答: https://stackoverflow.com/a/33079644/295246


編集:他の回答は、大きなファイル(つまり、stream=True)をダウンロードする必要がある場合に役立ちます。

49
HEADLESS_0NE

これらの答えを単純化し、大きなファイルをダウンロードする際のパフォーマンスを向上させるために、以下の方が少し効率的に機能する場合があります。

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   

GET要求でstream=Trueを設定することにより、r.iter_lines()をcsv.reader()に渡すときに、generatorto csv.reader()そうすることで、csv.reader()がfor row in readerで応答内の各行を遅延的に反復処理できるようにします。

これにより、処理を開始する前にファイル全体をメモリにロードする必要がなくなり、大きなファイルのメモリオーバーヘッドが大幅に削減されます

19
The Aelfinn

DictReader を使用して、{'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)
8
Antti Haapala

The Aelfinn および aheld からの回答が好きです。少し短くし、余分な部分を削除し、実際のデータソースを使用し、2.xおよび3.x互換にし、他の場所で見られる高レベルのメモリ効率を維持することによってのみ、それらを改善できます。

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)

2.xのみのバージョン(for row in csv.reader(r.iter_lines()):)はよりPythonicであるため、イテレータはUnicode文字列を生成する必要があるため(requestsbytesを使用するため) (短くて読みやすい)。とにかく、上記の2.x/3.xのソリューションは、OPによって記述された状況を処理しないことに注意してください。この状況では、読み込まれたデータに引用符なしで改行が見つかります。

ダウンロード(対処理)に関する実際のCSVファイルに関するOPの質問の一部については、that、2.xおよび3.x互換、最小、読み取り可能、およびメモリ効率:

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)
6
wescpy

ちょっとした検索から、ファイルがユニバーサル改行モードで開かれるべきだと理解しているので、応答コンテンツで直接行うことはできません(推測)。

タスクを完了するには、ダウンロードしたコンテンツを一時ファイルに保存するか、メモリで処理します。

ファイルとして保存:

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)

メモリ内:

(更新予定)

3
Ares Ou

ファイルが非常に大きい場合、リクエストのiter_linesメソッドを使用して、受け入れられた回答を更新できます。

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)
2
aheld

私はこのコードを使用します(Python 3を使用します):

import csv
import io
import requests

url = "http://samplecsvs.s3.amazonaws.com/Sacramentorealestatetransactions.csv"
r = requests.get(url)
r.encoding = 'utf-8'  # useful if encoding is not sent (or not sent properly) by the server
csvio = io.StringIO(r.text, newline="")
data = []
for row in csv.DictReader(csvio):
    data.append(row)
2
Michal Skop

次のアプローチは私にとってはうまくいきました。また、csv.reader()またはcsv.writer()関数を使用する必要もなかったので、コードがきれいになりました。コードは、Python2および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)

注-sixは、Python 2とPython 3の両方と互換性のあるコードを作成するのに役立つパッケージです。6に関する詳細については、 What from six.moves import urllib Pythonで行いますか?

1
aamir23