私はこの単純な問題に長い間苦労してきたので、私は助けを求めると思いました。国立医学図書館のftpサイトからジャーナル記事のリストをPython 3.3.2(Windows 7))に読み込もうとしています。ジャーナル記事は.csvファイルにあります。
私は次のコードを試しました:
import csv
import urllib.request
url = "ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/file_list.csv"
ftpstream = urllib.request.urlopen(url)
csvfile = csv.reader(ftpstream)
data = [row for row in csvfile]
次のエラーが発生します。
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
data = [row for row in csvfile]
File "<pyshell#4>", line 1, in <listcomp>
data = [row for row in csvfile]
_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)
私はバイトではなく文字列を扱うべきだと思いますか?単純な問題に関するヘルプ、および何が問題なのかについての説明をいただければ幸いです。
問題はurllib
がバイトを返すことに依存しています。証拠として、ブラウザでcsvファイルをダウンロードして、通常のファイルとして開くと、問題はなくなります。
同様の問題が解決されました here 。
適切なエンコーディングを使用して、バイトを文字列にデコードすることで解決できます。例えば:
_import csv
import urllib.request
url = "ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/file_list.csv"
ftpstream = urllib.request.urlopen(url)
csvfile = csv.reader(ftpstream.read().decode('utf-8')) # with the appropriate encoding
data = [row for row in csvfile]
_
最後の行はdata = list(csvfile)
である可能性もあります。これは読みやすい場合があります。
ちなみに、csvファイルは非常に大きいため、遅くなり、メモリを消費する可能性があります。たぶん、ジェネレータを使用することが望ましいでしょう。
EDIT:Steven Rumbalskiが提案したコーデックを使用するため、ファイル全体を読み取ってデコードする必要はありません。メモリ消費が削減され、速度が向上しました。
_import csv
import urllib.request
import codecs
url = "ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/file_list.csv"
ftpstream = urllib.request.urlopen(url)
csvfile = csv.reader(codecs.iterdecode(ftpstream, 'utf-8'))
for line in csvfile:
print(line) # do something with line
_
同じ理由でリストも作成されないことに注意してください。
すでに受け入れられている答えがありますが、requests
パッケージ(_urlib.request
_ )。
codecs.itercode()
を使用して元の問題を解決する基礎は、 受け入れられた回答 と同じです。
_import codecs
from contextlib import closing
import csv
import requests
url = "ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/file_list.csv"
with closing(requests.get(url, stream=True)) as r:
reader = csv.reader(codecs.iterdecode(r.iter_lines(), 'utf-8'))
for row in reader:
print row
_
ここでは、ネットワーク経由でファイル全体をロードすることを回避するために、requests
パッケージを通じて提供されるstreamingの使用も参照してください。最初にメモリ(ファイルが大きい場合は時間がかかる可能性があります)。
Python 3.6。で_urllib.request
_ではなくrequests
を使用していたので、それが役立ったので便利だと思いました。
いくつかのアイデア(たとえばclosing()
を使用)は、この類似の post から選択されます