Pandas read_csv do URL


138

Estou usando o Python 3.4 com IPython e tenho o seguinte código. Não consigo ler um arquivo csv a partir do URL fornecido:

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)

Eu tenho o seguinte erro

"Nome esperado do caminho do arquivo ou objeto parecido com arquivo, tipo"

Como posso consertar isso?


Você precisaria de algo como c=pd.read_csv(io.StringIO(s.decode("utf-8"))), mas você está recebendo html volta não um arquivo CSV para que ele não vai funcionar
Padraic Cunningham

3
Estou bastante certo de que o URL que você deseja é "https://raw.github.com/cs109/2014_data/blob/master/countries.csv".
precisa saber é o seguinte

@venom, escolheu a resposta mais popular como a mais acertada
ibodi 11/11/19

Respostas:


166

Atualizar

Dos pandas, 0.19.2agora você pode passar o URL diretamente .


Assim como o erro sugere, pandas.read_csvprecisa de um objeto semelhante a um arquivo como o primeiro argumento.

Se você quiser ler o csv de uma string, poderá usar io.StringIO(Python 3.x) ou StringIO.StringIO(Python 2.x) .

Além disso, para o URL - https://github.com/cs109/2014_data/blob/master/countries.csv - você está recebendo htmlresposta de retorno , não csv bruto, deve usar o URL fornecido pelo Rawlink na página do github para obtendo resposta csv bruta, que é - https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv

Exemplo -

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

E se a resposta for grande e eu quiser transmiti-la em vez de consumir memória para o conteúdo codificado, o conteúdo decodificado e o objeto StringIO?
akaihola

9
Na versão mais recente do pandas, você pode fornecer o URL diretamente, iec=pd.read_csv(url)
inodb

Curiosamente, tenho uma versão mais recente do pandas(0.23.4), mas não pude dar o URL diretamente. Essa resposta me ajudou a fazer isso funcionar.
Antti

1
"Atualização do pandas 0.19.2 agora você pode passar o URL diretamente." A menos que você não possa, porque precisa passar argumentos de autenticação, nesse caso o exemplo original é muito necessário.
Aaron Hall

Esta solução ainda é valiosa se você precisar de uma melhor manipulação de erros usando códigos HTTP que podem ser retornados pelo objeto de solicitação (ex: 500 -> nova tentativa pode ser necessária, 404 -> sem nova tentativa)
JulienV

235

Na versão mais recente do pandas ( 0.19.2), você pode transmitir diretamente o URL

import pandas as pd

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

parece que a utilização deste diretamente em vez de solicitações diretamente não usa solicitações de-cache , mesmo se usado
shadi

5
Esse código retorna urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)>por causa do protocolo https que o urllib não pode manipular.
multigoodverse

Para quem usa o Python 2, você precisará usar o Python 2.7.10+.
Avelis

Parece haver algum problema ao ler csv de um URL. Eu li o arquivo uma vez em um armazenamento local e uma vez na URL, continuava recebendo erros da URL. Ativei error_bad_lines = False e mais de 99% dos dados foram ignorados. O URL é link . Uma vez que eu ler o arquivo, a forma do conjunto de dados foi encontrado para ser (88,1), o que é completamente errado
Rishik Mani

10

Como eu comentei, você precisa usar um objeto StringIO e decodificar, ou seja, c=pd.read_csv(io.StringIO(s.decode("utf-8")))se estiver usando solicitações, precisará decodificar como .content retorna bytes se você usou .text, você só precisará passar s como está s = requests.get(url).textc = pd.read_csv(StringIO(s)).

Uma abordagem mais simples é passar o URL correto dos dados brutos diretamente para read_csv, você não precisa passar um arquivo como objeto, pode passar um URL para não precisar de solicitações:

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

print(c)

Resultado:

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

Dos documentos :

filepath_or_buffer :

string ou identificador de arquivo / StringIO A string pode ser um URL. Os esquemas de URL válidos incluem http, ftp, s3 e arquivo. Para URLs de arquivo, é esperado um host. Por exemplo, um arquivo local pode ser o arquivo: //localhost/path/to/table.csv


1
Você pode alimentar o URL diretamente para os pandas read_csv! claro! essa é uma solução muito mais simples do que a que encontrei! : D
PabTorre 4/15

1
@ pabtorre, sim, um exemplo de por que ler os documentos é uma boa ideia.
Padraic Cunningham

6

O problema que você está tendo é que a saída que você obtém na variável 's' não é um csv, mas um arquivo html. Para obter o csv bruto, você deve modificar o URL para:

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

Seu segundo problema é que o read_csv espera um nome de arquivo. Podemos resolver isso usando o StringIO do módulo io. O terceiro problema é que request.get (url) .content fornece um fluxo de bytes, podemos resolver isso usando o request.get (url) .text.

O resultado final é este código:

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

resultado:

>>> c.head()
    Country  Region
0   Algeria  AFRICA
1    Angola  AFRICA
2     Benin  AFRICA
3  Botswana  AFRICA
4   Burkina  AFRICA

2
url = "https://github.com/cs109/2014_data/blob/master/countries.csv"
c = pd.read_csv(url, sep = "\t")

Forneça explicações sobre como sua solução funciona.
Selim Yıldız

0

Para importar dados através de URL em pandas, basta aplicar o código abaixo simples, que funciona realmente melhor.

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

Se você está tendo problemas com dados brutos, basta colocar 'r' antes do URL

import pandas as pd
train = pd.read_table(r"https://urlandfile.com/dataset.csv")
train.head()
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.