Pandas read_csv von der URL

138

Ich verwende Python 3.4 mit IPython und habe den folgenden Code. Ich kann keine CSV-Datei von der angegebenen URL lesen:

import pandas as pd
import requests

url="https://github.com/cs109/2014_data/blob/master/countries.csv"
s=requests.get(url).content
c=pd.read_csv(s)

Ich habe den folgenden Fehler

"Erwarteter Dateipfadname oder dateiähnliches Objekt, Typ erhalten"

Wie kann ich das beheben?

Gift
quelle
Sie würden so etwas wie brauchen, c=pd.read_csv(io.StringIO(s.decode("utf-8")))aber Sie bekommen HTML zurück, keine CSV-Datei, so dass es nicht funktionieren wird
Padraic Cunningham
3
Ich bin mir ziemlich sicher, dass die gewünschte URL lautet "https://raw.github.com/cs109/2014_data/blob/master/countries.csv".
Kylie.a
@venom, wählte populärere Antwort als die richtige
ibodi

Antworten:

166

Aktualisieren

Von Pandas können 0.19.2Sie jetzt einfach die URL direkt übergeben .


Wie der Fehler andeutet, wird pandas.read_csvals erstes Argument ein dateiähnliches Objekt benötigt.

Wenn Sie die CSV aus einer Zeichenfolge lesen möchten, können Sie io.StringIO(Python 3.x) oder StringIO.StringIO(Python 2.x) verwenden .

Außerdem erhalten Sie für die URL - https://github.com/cs109/2014_data/blob/master/countries.csv - eine htmlAntwort, keine rohe CSV. Verwenden Sie die URL, die durch den RawLink auf der Github-Seite für angegeben wird Erhalten einer rohen CSV-Antwort: https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv

Beispiel -

import pandas as pd
import io
import requests
url="https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv"
s=requests.get(url).content
c=pd.read_csv(io.StringIO(s.decode('utf-8')))
Anand S Kumar
quelle
Was ist, wenn die Antwort groß ist und ich sie streamen möchte, anstatt Speicher für den codierten Inhalt, den decodierten Inhalt und das StringIO-Objekt zu verbrauchen?
Akaihola
9
In der neuesten Version von Pandas können Sie die URL direkt geben, dhc=pd.read_csv(url)
inodb
Seltsamerweise habe ich eine neuere Version von pandas(0.23.4), aber ich konnte die URL nicht direkt angeben. Diese Antwort hat mir geholfen, das zum Laufen zu bringen.
Antti
1
"Update Von Pandas 0.19.2 können Sie jetzt einfach die URL direkt übergeben." Es sei denn, Sie können nicht, weil Sie Authentifizierungsargumente übergeben müssen. In diesem Fall wird das ursprüngliche Beispiel dringend benötigt.
Aaron Hall
Diese Lösung ist immer noch nützlich, wenn Sie eine bessere Fehlerbehandlung mit HTTP-Codes benötigen, die möglicherweise vom Anforderungsobjekt zurückgegeben werden (Beispiel: 500 -> Wiederholung erforderlich, 404 -> keine Wiederholung)
Juli
235

In der neuesten Version von pandas ( 0.19.2) können Sie die URL direkt übergeben

import pandas as pd

url="https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv"
c=pd.read_csv(url)
inodb
quelle
Es scheint, dass die direkte Verwendung anstelle von Anfragen nicht den Anforderungs-Cache verwendet, selbst wenn er verwendet wird
Shadi
5
Dieser Code wird urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)>aufgrund des https-Protokolls zurückgegeben, das urllib nicht verarbeiten kann.
Multigoodverse
Für diejenigen, die Python 2 verwenden, müssen Sie Python 2.7.10+ verwenden.
Avelis
Es scheint ein Problem beim Lesen von CSV von einer URL zu geben. Ich habe die Datei einmal aus einem lokalen Speicher und einmal aus der URL gelesen und immer wieder Fehler von der URL erhalten. Ich habe dann error_bad_lines = False aktiviert und mehr als 99% der Daten wurden ignoriert. Die URL ist Link . Nachdem ich die Datei gelesen hatte, wurde festgestellt, dass die Form des Datensatzes (88,1) ist, was völlig falsch ist
Rishik Mani
10

Wie ich bereits sagte, müssen Sie ein StringIO-Objekt verwenden und dekodieren, dh c=pd.read_csv(io.StringIO(s.decode("utf-8")))wenn Sie Anforderungen verwenden, müssen Sie dekodieren, da .content Bytes zurückgibt, wenn Sie .text verwenden, müssen Sie nur s so übergeben, wie es s = requests.get(url).textc = ist pd.read_csv(StringIO(s)).

Ein einfacherer Ansatz besteht darin, die korrekte URL der Rohdaten direkt an zu übergeben read_csv. Sie müssen kein dateiähnliches Objekt übergeben. Sie können eine URL übergeben, sodass Sie überhaupt keine Anforderungen benötigen:

c = pd.read_csv("https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv")

print(c)

Ausgabe:

                              Country         Region
0                             Algeria         AFRICA
1                              Angola         AFRICA
2                               Benin         AFRICA
3                            Botswana         AFRICA
4                             Burkina         AFRICA
5                             Burundi         AFRICA
6                            Cameroon         AFRICA
..................................

Aus den Dokumenten :

Dateipfad_oder_Buffer :

Zeichenfolge oder Dateihandle / StringIO Die Zeichenfolge kann eine URL sein. Gültige URL-Schemata umfassen http, ftp, s3 und file. Für Datei-URLs wird ein Host erwartet. Eine lokale Datei könnte beispielsweise die Datei //localhost/path/to/table.csv sein

Padraic Cunningham
quelle
1
Sie können die URL direkt an pandas read_csv weitergeben! natürlich! Das ist eine viel einfachere Lösung als die, die ich gefunden habe! : D
PabTorre
1
@pabtorre, yep, ein Beispiel dafür, warum das Lesen der Dokumente eine gute Idee ist.
Padraic Cunningham
6

Das Problem ist, dass die Ausgabe, die Sie in die Variable 's' erhalten, keine CSV-Datei, sondern eine HTML-Datei ist. Um die rohe CSV zu erhalten, müssen Sie die URL ändern in:

' https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv '

Ihr zweites Problem ist, dass read_csv einen Dateinamen erwartet. Wir können dies mithilfe von StringIO aus dem io-Modul lösen. Das dritte Problem ist, dass request.get (url) .content einen Bytestream liefert. Wir können dies stattdessen mit dem request.get (url) .text lösen.

Endergebnis ist dieser Code:

from io import StringIO

import pandas as pd
import requests
url='https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv'
s=requests.get(url).text

c=pd.read_csv(StringIO(s))

Ausgabe:

>>> c.head()
    Country  Region
0   Algeria  AFRICA
1    Angola  AFRICA
2     Benin  AFRICA
3  Botswana  AFRICA
4   Burkina  AFRICA
PabTorre
quelle
2
url = "https://github.com/cs109/2014_data/blob/master/countries.csv"
c = pd.read_csv(url, sep = "\t")
Gursimran Singh
quelle
Bitte erläutern Sie, wie Ihre Lösung funktioniert.
Selim Yıldız
0

Um Daten über URL in Pandas zu importieren, wenden Sie einfach den folgenden einfachen Code an, der tatsächlich besser funktioniert.

import pandas as pd
train = pd.read_table("https://urlandfile.com/dataset.csv")
train.head()

Wenn Sie Probleme mit Rohdaten haben, setzen Sie einfach 'r' vor die URL

import pandas as pd
train = pd.read_table(r"https://urlandfile.com/dataset.csv")
train.head()
Jain
quelle