Last active
August 21, 2019 02:41
-
-
Save jobdiogenes/2db28551f0c100ecd034206494d08d16 to your computer and use it in GitHub Desktop.
data_science_gist_02_pt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"nbformat": 4, | |
"nbformat_minor": 0, | |
"metadata": { | |
"colab": { | |
"name": "data_science_gist_02_pt", | |
"version": "0.3.2", | |
"provenance": [], | |
"private_outputs": true, | |
"collapsed_sections": [], | |
"include_colab_link": true | |
}, | |
"kernelspec": { | |
"name": "python3", | |
"display_name": "Python 3" | |
} | |
}, | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "view-in-github", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"<a href=\"https://colab.research.google.com/gist/jobdiogenes/2db28551f0c100ecd034206494d08d16/data_science_gist_02_pt.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "LSgBloY4DdVf", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"[Índice](https://github.com/jobdiogenes/data-science-recipes/blob/master/gists/index.md)\n", | |
"# Série de Receitas para Ciência de Dados\n", | |
"## Episódio 2 - Repositórios: extraindo dados do Fishbase com python usando REST API \n", | |
"### Introdução\n", | |
">**Mas que diabos é isso?** Geralmente ao ver siglas de áreas que não conhecemos ficamos assustados, ou mesmo nas áreas que atuamos sempre aparece uma determinada sigla que não conhecemos ou que tem um signifcado diferente em especilidades diferentes. Então, primeiramente não se assuste, **API** é apenas mais uma sigla. \n", | |
"\n", | |
">**API** vem do inglês de Application Program Interface, ou seja Interface de Programação de Aplicativos. Que nada mais é do que um conjunto de regras definidas para se comunicar com um Aplicativo (software). Na biologia pense nisso como um taxonomista e nos métodos padronizados para descrever e classificar uma espécie, gênero, ou família por exemplo. Logo a frente você perceber muita semelhança da organização de uma **API** do tipo **REST** (_Representational State Transfer_) com uma hierarquia taxonômica e detalhamentos.\n", | |
"\n", | |
"Pesquisadores e cientistas são ávidos por base da dados (repositórios), para obter informações para suas pesquisas, que podem ser uma uma simples confirmação de nome científico, usar banco de dados genéticos para comparar com dados genéticos seus, ou extrair massas de dados para fazer análises sobre elas, usando critérios espaciais como na ecologia. Não, não se preocupe, não vamos fazer uma análise espacial multivariada agora, nem aplicar aprendizado de máquina para identificar padrões de expressão e comunicação automaticamente. Aqui é um tijolo de cada vez. \n", | |
"\n", | |
"No entanto, quando começamos a fazer consultas à essas bases, hoje em dia, o fazemos através de navegadores, indo até o endereço de internet (URL) da mesma, e usamos sua interface para realizar as consultas. É claro esse modo de pesquisa nos ajuda, porém começa a ficar pouco prático quando quantidade de consultas vai crescendo e a diversidade de informações vai expandindo. E o pior, para coletar os dados de resultados temos que ficar selecionado, copiando e colando, que além de cansativo podemos cometer erros. Fazer isso uma ou 2 vezes, é tranquilo, mas conforme vai aumentando o esforço cresce muito, nos causa cansaço visual e até Lesão por Esforço Repetitivo, e toma muito tempo. Um pesquisador agindo assim pode ter de reduzir muito a amplitude de dados pesquisados, pois vai consumir muito tempo e poderá ainda cometer erros ou pior ter gasto muito tempo para obter algo que não atendeu as necessidades. \n", | |
"\n", | |
"Para um pesquisador com prazos, pode ser e emocionalmente muito desgantante ter de gastar muito tempo para obter e analisar dados de forma manual, pelo tempo que consome e a pressão para não cometer erros. E se isso ainda não atender as necessidades do plano de pesquisa ou insuficientes, pode se tornar algo extremamente frustante. \n", | |
"\n", | |
">**PS** é também possível extrair dado de forma automática de repositórios que não possuem API e só disponibilizam uma interface WEB. No entanto, isso é um pouco mais complexo e não iremos tratar disso por enquanto. Outra questão de não fazer isso, é que alguns repositórios não oferecem API pois não permitem extração de dados de forma automatizada, o que é uma pena. \n", | |
"\n", | |
"### Meta\n", | |
"Por isso a meta desse episódio é tornar familiar aos pesquisadores, os conceitos e a técnicas para extração de dados de repositórios usando API, para que assim possam fazer suas próprias pesquisas de forma automática, escrevendo suas próprias rotinas, ou quando avaliar uma rotina desenvolvida por outros, ser capaz de entender, conhecer seus limites ou mesmo identificar erros. Mesmo que não se torne um expert, que espero que se tornem ao final, mas conhecer como isso é feito é fundamental para qualquer pesquisador, pois amplia sua capacidade de visualizar os dados e compreender as amostras extraídas por outrem.\n", | |
"\n", | |
"### O que iremos ver ?\n", | |
"Bom, antes de mais nada, para realizar os exercícios desse episódio é importante já estar familiar com o conteúdo do [Episódio 1](https://gist.github.com/jobdiogenes/a8d65fcabc8f8a47473769a9ba970fe0). Então agora abra o Python 3, num dos meios sugeridos no episódio 1. E\n", | |
"\n", | |
"Neste episódio temos os seguintes iténs:\n", | |
"1. [X] Descrição de como funcionam API REST de repositórios.\n", | |
"1. [X] Extraindo dados Fishbase usando a API REST.\n", | |
"\n", | |
"> Como dito no primeiro episódio, os novos episódios serão menores.\n", | |
"\n", | |
"### Item 1 - Descrição de uma API REST\n", | |
"Bom antes de falar sobre a API REST, em uma nova aba do navegador de internet vá a página de pesquisa [FishBase.org](www.fishbase.org), para você se familiarizar com o conteúdo oferecido pelo repositório. Como eu disse no primeiro episódio o primeiro passo é sempre conhecer o que oferecem os repositórios, para depois aos poucos criar sua estratégia de extração de dados. \n", | |
"\n", | |
"E lá faça uma pesquisa pela espécie: _Serrasalmus marginatus_, no resultado da pesquisa retorna uma página rica em informações,\n", | |
"com foto da espécie, classificação, descrição, etc. A forma apresentada atende quem esta visualizando a página e é possível extrair informações copiando e colando e até as imagens.\n", | |
"\n", | |
"Esse conteúdo que recebemos ao acessar uma página por um navegador usa o protocolo HTTP, que vemos sempre nos endereços no navegador e o coteúdo que retorna ao navegador é em geral o HTML, que por fim é processado e apresentado ao usuário. \n", | |
"\n", | |
"Por exemplo o conteúdo HTML\n", | |
"```html\n", | |
"<h1>Peixes predadores </h2>\n", | |
"<h2>Piranha</h2>\n", | |
"<p>Nome científico: <i>Serrasalmus marginatus</i></p>\n", | |
"```\n", | |
"\n", | |
"O navegador processa e exibe como: \n", | |
"\n", | |
"> # Peixes predadores\n", | |
">## Piranha\n", | |
">Nome científico: _Serrasalmuls mergisnatus_\n", | |
"\n", | |
"O protocolo HTTP também usa os conceitos do REST, por exemplo quando digitamos:\n", | |
"```\n", | |
"https://en.wikipedia.org/wiki/Piranha\n", | |
"```\n", | |
"\n", | |
"Estamos através do HTTP usando os conceitos do REST, onde após digitar o endereço o navegador (Firefox, Chrome, etc) envia um comando de solicitação de dados ao endereço de domínio destino (en.wikipedi.org) contendo os parâmetros **/wiki/Piranha**. \n", | |
"\n", | |
"No entanto conforme a WEB foi desenvolvendo o conteúdo do HTML foi crescendo incluindo uma série de recursos para mellhorar o visual, exibir imagens, sons e vídeos, lidar com a interface com o usuário. Para ver essa complexidade, você pode clicar em algum lugar vazio desta página com o botão direito e pedir para ver o código fonte. Vai encontrar um conteúdo grande, que não lhe parecerá muito compreensível.\n", | |
"\n", | |
"No entando se você esta apenas interessado em dados, não faz sentido receber um conteúdo tão grande complexo. As API REST, como outras APIS de começaram então a se desenvolver para atender a essa necessidade. Ao invés do HTML, as API REST se comunicam em geral com 3 tipos de formatos, são eles:\n", | |
"\n", | |
">**XML**\n", | |
"```XML\n", | |
"<fish>\n", | |
" <genus>Serrasalmus</genre>\n", | |
" <species>spilopleura</specie>\n", | |
" <author>Kner, 1858</autor>\n", | |
" <spec_code>11973</spec_code>\n", | |
"</fish> \n", | |
"```\n", | |
"\n", | |
"> **JSON**\n", | |
"```json\n", | |
"{ fish: {\n", | |
" genus: \"Serrasalmus\",\n", | |
" species: \"spiplopleura\",\n", | |
" author: \"Kner, 1858\",\n", | |
" \"spec code\": 11973\n", | |
" }\n", | |
"}\n", | |
"```\n", | |
"\n", | |
">**YAML**\n", | |
"```yaml\n", | |
"fish:\n", | |
"genus: Serrasalmus\n", | |
"species: spilopleura\n", | |
"author: Kner, 1958\n", | |
"spec code: 11973\n", | |
"```\n", | |
"\n", | |
"São mais compreensívos que o HTML, pois se quer apenas dados e não lidar com o visual de uma página.\n", | |
"A maioria dos repositórios permitem em geral XML e JSON, e algumas o YAML, o Python oferece recursos, através de **bibliotecas** para lidar com os três formatos. Mas em geral usamos mais o JSON, pois é menos verboso e mais rápido. O YAML, quando disponível é muito útil quando queremos ver o conteúdo do repositório para entender.\n", | |
"\n", | |
"A comunicação em geral é feita pelo cliente (o seu programa) solicitando ao repositório informações através de parâmetros passados.\n", | |
"E após enviarmos esses parâmetros, tratamos as informações que retornam. \n", | |
"\n", | |
"Em geral temos de saber se os parâmetros que passamos estão corretos e retornam dados, ou se deu algum erro. Os códigos seguem o modelo padrão HTTP com algumas modificações em alguns casos, mas no geral são os mesmos. Por exemplo para resposta sem erro o código é: **200**. \n", | |
"\n", | |
"A documentação da API do fish base pode ser encontrada aqui: (https://fishbaseapi.readme.io)\n", | |
"\n", | |
"Vamos ao primeiro exemplo: \n", | |
"\n", | |
"\n", | |
"\n", | |
"\n", | |
"\n", | |
"\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "FZ92ymjniSkf", | |
"colab_type": "code", | |
"colab": {} | |
}, | |
"source": [ | |
"# Primeiro importamos a função get da biblioteca requests que é uma da bibliotecas \n", | |
"# disponíveis para lidar com consultas a endereços de internet (URL)\n", | |
"# poderiamos importar toda a biblioteca escrevendo: import requests as r \n", | |
"# onde o r seria um apelido e o uso da função get como outras funções disponíveis \n", | |
"# seria feita como r.get() \n", | |
"#\n", | |
"from requests import get\n", | |
"# definimos uma variável\n", | |
"h = \"https://fishbase.ropensci.org/\"\n", | |
"# vamos pesquisar por Serrasalmus marginatus\n", | |
"# maisculos e minusculos são desconsiderados\n", | |
"r = get(h+'/taxa?Genus=serrasalmus&Species=spilopleura')\n", | |
"# exibir o codigo do retorno\n", | |
"print('Codigo R:',r.status_code)\n", | |
"# exibindo o texto de conteúdo\n", | |
"print(r.text)\n", | |
"print(type(r.text))\n", | |
"\n", | |
"# algo com rota (route) errada (tax ao inves de taxa) retorna código 404\n", | |
"err = get(h+'/tax?genus=serrasalmus&Species=spilopleura')\n", | |
"print('Código err:',err.status_code)\n", | |
"print(err.text)\n", | |
"\n", | |
"# algo com termo errado (genus, ao invés de Genus) volta com dados errados. \n", | |
"# ou seja é preciso ter cuidado\n", | |
"r2 = get(h+'taxa?genus=serrasalmus&Species=spilopleura')\n", | |
"print(r2.status_code)\n", | |
"print(r2.text,'\\n')\n", | |
"\n", | |
"# como exbido acima o conteúdo r.text é to tipo str,\n", | |
"# apesar de estar no formato JSON. \n", | |
"# para ser útil teriamos de converter para JSON que por sua vez \n", | |
"# se tornaria um dic do Python.\n", | |
"# para tanto existe a biblioteca json\n", | |
"import json\n", | |
"dados = json.loads(r.text)\n", | |
"print('Tipo Dado:',type(dados))\n", | |
"print(dados,'\\n')\n", | |
"\n", | |
"# por outro lado a função get pode nos facilitar, pois permite retornar \n", | |
"# diretamente json sem usar a biblioteca 'json' e se der erro vem o texto com o erro. \n", | |
"dic = get(h+'/taxa?Genus=serrasalmus&Species=spilopleura').json()\n", | |
"print('Tipo d:',type(dic))\n", | |
"\n", | |
"# é claro passar parametros assim pode levar a erros e não ser muito prático.\n", | |
"# felizmente há outra forma de passar parâmetros\n", | |
"# lembra do tipo dicionário?\n", | |
"\n", | |
"buscar = {\n", | |
" 'Genus' : 'serrasalmus',\n", | |
" 'Species' : ''\n", | |
"}\n", | |
"\n", | |
"buscar['Species'] = 'spilopleura'\n", | |
"\n", | |
"d = get(h+'/taxa', params = buscar).json()\n", | |
"print('\\nBem mais pratico')\n", | |
"print(d)\n", | |
"\n", | |
"# é claro como vimos no episódio 1 podemos acessar só o dado que nos interessa\n", | |
"# por exemplo o código da especie SpecCode, que esta data.\n", | |
"speccode = d['data'][0]['SpecCode']\n", | |
"print('SpecCode é:',speccode)\n", | |
"print('Total encontrado é:',d['count'])\n", | |
"# observou que o count é o nº de elementos em data\n", | |
"# " | |
], | |
"execution_count": 0, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "ZkzN2I9qLQeE", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Bom já aprendemos como acessar o repositório e como pegar dados dele.\n", | |
"\n", | |
"Mas no exemplo pegamos apenas uma espécie. e se quisermos todos os gêneros? como lidar com isso?\n", | |
"\n", | |
"vamos ao exemplo:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "yrqQ34sONPL3", | |
"colab_type": "code", | |
"colab": {} | |
}, | |
"source": [ | |
"# aqui vamos repetir a definição de funções pois você pode estar começando daqui.\n", | |
"# mas se esta na linha do comando do Python3 ou do ipython, e fazendo em seguida não seria necessário. ou bastaria\n", | |
"# apertar a seta acima e acessar os comando anteriores\n", | |
"from requests import get\n", | |
"h = \"https://fishbase.ropensci.org/\"\n", | |
"pars = {\n", | |
" 'Genus' : 'serrasalmus',\n", | |
" 'Species' : ''\n", | |
"}\n", | |
"\n", | |
"# observe que encontrou 'count' 31 mas retornou 'returned' 10\n", | |
"d = get(h+'taxa', params = pars).json()\n", | |
"print(d)\n", | |
"\n", | |
"# por padrão o fishbase tem um limite 'limit' de 10 e começa pelo 'offset' 0 \n", | |
"# assim para pegar todos \n", | |
"pars['limit'] = 31\n", | |
"d = get(h+'taxa', params = pars).json()\n", | |
"print('Total:',d['count'],', Recebido:',d['returned'],'\\n')\n", | |
"\n", | |
"# é claro carregar um volume muito grande de dados poderia encher a memória\n", | |
"# então vamos fazer isso usando ciclos e baixando de 12 em 12 por exemplo.\n", | |
"# e exibir os nomes das espécies e o SpecCode\n", | |
"# para isso vamos usar os parametros 'limit' e depois o 'offset'\n", | |
"# para ir buscando \n", | |
"passo = 12\n", | |
"pars['limit'] = passo\n", | |
"r = get(h+'taxa', params = pars).json()\n", | |
"print('Total:',r['count'],', Recebido:',r['returned'],'\\n')\n", | |
"\n", | |
"total = r['count']\n", | |
"posicao = 0 # posição inicial \n", | |
"print('--------------------------------------------')\n", | |
"while total > passo:\n", | |
" # ***observe aqui****, que antes foi verificado que o campo 'data' \n", | |
" # é uma lista 'list' por isso é muito importante sempre olhar os dados \n", | |
" # para ver como eles são e assim saber como trabalhar com eles \n", | |
" especies = r['data']\n", | |
" print('de:',posicao,' à ',posicao+passo)\n", | |
" print('--------------------------------------------')\n", | |
" for especie in especies:\n", | |
" print('SpecCode:',especie['SpecCode'])\n", | |
" print('Gênero:',especie['Genus'])\n", | |
" print('Espécie:',especie['Species'],'\\n')\n", | |
" print('--------------------------------------------')\n", | |
" posicao += passo\n", | |
" pars['offset'] = posicao \n", | |
" total -= passo\n", | |
"\n", | |
"print('Fim :)')" | |
], | |
"execution_count": 0, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "Y6-5mAoZ50S5", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"### **Tarefa 01**\n", | |
"No [Episódio 1](https://gist.github.com/jobdiogenes/a8d65fcabc8f8a47473769a9ba970fe0) você aprendeu como exibir todos os pares de dados de um dicionário. Use esse conhecimento e refaça a parte final do exemplo acima onde se exibe 'SpecCode', Genus e Species, para exibir todos os campos. A resposta você pode ver [aqui](https://github.com/jobdiogenes/data-science-recipes/blob/master/gists/code/answer-e02t01.py). Não veja isso agora. Faça esta tarefa. Mais uma dica você aprendeu isso ao final do episódio 01\n", | |
"\n", | |
"***\n", | |
"\n", | |
"## Fim do episódio 02\n", | |
"No próximo episódio iremos ver extrair dados integrando várias partes (rotas) dos dados oferecidos pelo repositório\n", | |
"\n", | |
"> Você já encontrou repositórios que lhe interessam? \n", | |
"\n", | |
"> Se você ama taxonomia de espécies vai gostar de conhecer o [Catalago of Life](http://www.catalogueoflife.org/) que é um repositório que aglutina informações oriundas de diversas fontes para todo reino de espécies da vida (na terra por enquanto)." | |
] | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment