Pandy read_csv z adresu url

138

Używam języka Python 3.4 z IPythonem i mam następujący kod. Nie mogę odczytać pliku CSV z podanego adresu URL:

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)

Mam następujący błąd

„Oczekiwana nazwa ścieżki do pliku lub obiekt podobny do pliku, pobrano typ”

Jak mogę to naprawić?

jad
źródło
Potrzebowałbyś czegoś takiego, c=pd.read_csv(io.StringIO(s.decode("utf-8")))ale otrzymujesz z powrotem html, a nie plik csv, więc to nie zadziała
Padraic Cunningham
3
Jestem prawie pewien, że żądany adres URL to "https://raw.github.com/cs109/2014_data/blob/master/countries.csv".
kylie.a
@venom, wybrał bardziej popularną odpowiedź jako właściwą
ibodi

Odpowiedzi:

166

Aktualizacja

Z pand 0.19.2możesz teraz bezpośrednio przekazać adres URL .


Tak jak sugeruje błąd, pandas.read_csvjako pierwszy argument potrzebny jest obiekt podobny do pliku.

Jeśli chcesz odczytać plik csv z łańcucha, możesz użyć io.StringIO(Python 3.x) lub StringIO.StringIO(Python 2.x) .

Również w przypadku adresu URL - https://github.com/cs109/2014_data/blob/master/countries.csv - otrzymujesz htmlodpowiedź zwrotną, a nie surowy csv, powinieneś użyć adresu URL podanego w Rawlinku na stronie github dla uzyskiwanie nieprzetworzonej odpowiedzi csv, czyli - https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv

Przykład -

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
źródło
Co się stanie, jeśli odpowiedź jest duża i chcę ją przesyłać strumieniowo, zamiast zużywać pamięć na zawartość zakodowaną, zdekodowaną i obiekt StringIO?
akaihola
9
W najnowszej wersji pandy można podać adres URL bezpośrednio tjc=pd.read_csv(url)
inodb
Co ciekawe, mam nowszą wersję pandas(0.23.4), ale nie mogłem bezpośrednio podać adresu URL. Ta odpowiedź pomogła mi w uruchomieniu.
Antti
1
„Aktualizacja z pand w wersji 0.19.2, możesz teraz bezpośrednio przekazać adres URL”. Chyba że nie możesz, ponieważ musisz przekazać argumenty uwierzytelniające, w takim przypadku oryginalny przykład jest bardzo potrzebny.
Aaron Hall
To rozwiązanie jest nadal cenne, jeśli potrzebujesz lepszej obsługi błędów przy użyciu kodów HTTP, które mogą być zwracane przez obiekt żądania (np.: 500 ->
ponowna próba
235

W najnowszej wersji pandas ( 0.19.2) możesz bezpośrednio podać adres URL

import pandas as pd

url="https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv"
c=pd.read_csv(url)
inodb
źródło
wygląda na to, że używanie tego bezpośrednio zamiast żądań bezpośrednio nie używa pamięci podręcznej żądań, nawet jeśli jest używane
shadi
5
Ten kod powraca z urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)>powodu protokołu https, którego urllib nie obsługuje.
multigoodverse
Osoby korzystające z Pythona 2 będą musiały używać Pythona 2.7.10+.
avelis
Wydaje się, że wystąpił problem z odczytem pliku csv z adresu URL. Czytałem plik raz z pamięci lokalnej i raz z adresu URL, ciągle otrzymywałem błędy z adresu URL. Następnie włączyłem error_bad_lines = False i ponad 99% danych zostało zignorowanych. Adres URL to link . Kiedy przeczytałem plik, okazało się, że kształt zbioru danych to (88,1), co jest całkowicie błędne
Rishik Mani
10

Jak skomentowałem, musisz użyć obiektu StringIO i zdekodować, tj. c=pd.read_csv(io.StringIO(s.decode("utf-8")))Jeśli używasz żądań, musisz zdekodować, ponieważ .content zwraca bajty, jeśli użyłeś .text, po prostu musisz przekazać s tak, jak jest s = requests.get(url).textc = pd.read_csv(StringIO(s)).

Prostszym podejściem jest przekazanie prawidłowego adresu URL surowych danych bezpośrednio do read_csv, nie musisz przekazywać pliku takiego jak obiekt, możesz przekazać adres URL, aby w ogóle nie potrzebować żądań:

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

print(c)

Wynik:

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

Z dokumentów :

filepath_or_buffer :

ciąg lub uchwyt pliku / StringIO Ciąg może być adresem URL. Prawidłowe schematy adresów URL obejmują http, ftp, s3 i file. W przypadku adresów URL plików oczekiwany jest host. Na przykład lokalny plik może mieć postać file: //localhost/path/to/table.csv

Padraic Cunningham
źródło
1
Możesz podać adres URL bezpośrednio do pandy read_csv! oczywiście! to znacznie prostsze rozwiązanie niż to, które znalazłem! :RE
PabTorre
1
@pabtorre, tak, przykład, dlaczego czytanie dokumentów jest dobrym pomysłem.
Padraic Cunningham
6

Problem polega na tym, że wynik, który otrzymujesz do zmiennej 's', nie jest plikiem csv, ale plikiem html. Aby uzyskać nieprzetworzony plik csv, musisz zmodyfikować adres URL na:

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

Drugim problemem jest to, że read_csv oczekuje nazwy pliku, możemy to rozwiązać za pomocą StringIO z modułu io. Trzeci problem polega na tym, że request.get (url) .content dostarcza strumień bajtów, możemy to rozwiązać za pomocą request.get (url) .text.

Wynik końcowy to ten kod:

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

wynik:

>>> c.head()
    Country  Region
0   Algeria  AFRICA
1    Angola  AFRICA
2     Benin  AFRICA
3  Botswana  AFRICA
4   Burkina  AFRICA
PabTorre
źródło
2
url = "https://github.com/cs109/2014_data/blob/master/countries.csv"
c = pd.read_csv(url, sep = "\t")
Gursimran Singh
źródło
Podaj wyjaśnienie, jak działa Twoje rozwiązanie.
Selim Yıldız
0

Aby zaimportować dane przez adres URL w pandach, po prostu zastosuj prosty poniższy kod, który działa lepiej.

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

Jeśli masz problemy z nieprzetworzonymi danymi, po prostu wstaw „r” przed adresem URL

import pandas as pd
train = pd.read_table(r"https://urlandfile.com/dataset.csv")
train.head()
jain
źródło