Uma das coisas mais divertidas de se fazer com um computador é programá-lo para que busque informações na web para que não precisemos ficar clicando em um monte de páginas até chegar à informação que desejamos.
Poderíamos escrever um programa para buscar e mostrar os próximos horários de ônibus de determinada linha de uma forma mais amigável do que o portal da empresa de transporte urbano (busaoemfloripa). Ou então, poderíamos agregar várias informações de estações de monitoramento de chuvas e nível de rios para criar um sistema de apoio à população em épocas de cheia dos rios (enchentes.org). E que tal um programinha que busque na web o horário em que o seu programa de TV favorito será transmitido e que emita um alerta no seu desktop quando estiver chegando a hora? São várias as possibilidades de pequenos aplicativos que podem vir a tornar a nossa vida mais prática. Mas, para implementá-los, precisamos saber fazer algumas coisas:
- Acessar recursos que estão na web através de nossos programas.
- Filtrar os dados que são retornados nesses recursos para que possamos utilizá-los em nosso programa.
Nesse post, veremos como fazer para acessar recursos da web via HTTP. Mais tarde, em um post futuro, veremos como filtrar os dados retornados para usarmos em nossos programas.
Acessando a web com a API Requests
Antes de mais nada, para seguir este post, você precisará instalar o módulo requests.
Instalando o módulo requests
O módulo pode ser instalado via PIP:
$ pip install requests
Outras formas de instalação podem ser vistas em: http://docs.python-requests.org/en/latest/user/install/
Acessando um recurso simples
Usar o módulo requests é muito simples. Vamos começar acessando um recurso simples na web, como a lista de notícias do reddit programming:
>>> import requests
>>> response = requests.get('http://www.reddit.com/r/programming/')
>>> print response.status_code # 200 significa requisição OK
200
>>> print len(response.content)
87773
>>> print response.content[:100] # imprimindo só os 100 primeiros chars
<!doctype html><html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" ><head><title>prog
A função requests.get() obtém um recurso qualquer através de uma URL passada como argumento. O caso acima é o mais simples possível, pois sequer requer autenticação para fazer a requisição. A chamada a essa função retorna um objeto do tipo Response, que dentre outras coisas contém o status da requisição, que é um código numérico indicando o que aconteceu com a requisição. Esse status pode ser checado antes de acessarmos o conteúdo da requisição, para verificar se esta ocorreu com sucesso ou não.
O conteúdo da resposta enviada pelo servidor é armazenado no atributo content da resposta e pode ser acessado como qualquer outro atributo (response.content no código acima). Como você pode ver, o conteúdo retornado foi um tanto quanto grande (uma string de comprimento 87773), e por isso eu trunquei a impressão do conteúdo no código acima.
Possíveis problemas
Vamos tentar acessar um recurso inválido, como: http://www.google.com/umrecursoinvalido. Se tentarmos acessá-lo via browser, teremos a seguinte resposta:
Ou seja, realizamos uma requisição e o status dessa requisição é 404, que ocorre quando conseguimos nos conectar ao servidor, mas este não encontra o recurso solicitado. Veja o que acontece em nosso código:
>>> response = requests.get('http://www.google.com/umrecursoinvalido')
>>> print response.status_code
404
Outro erro comum é fazermos uma requisição para uma URL inexistente (que não possui mapeamento nos DNS), como por exemplo: http://umaurlquenaoapontapranada.com/. Nesse caso, é disparada uma exceção de erro de conexão, visto que não é possível estabelecer uma conexão com o servidor, sendo impossível assim ter um código de status:
>>> response = requests.get('http://umaurlquenaoapontapranada.com')
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib/python2.7/dist-packages/requests/api.py", line 52, in get
return request('get', url, **kwargs)
File "/usr/lib/python2.7/dist-packages/requests/api.py", line 40, in request
return s.request(method=method, url=url, **kwargs)
File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 229, in request
r.send(prefetch=prefetch)
File "/usr/lib/python2.7/dist-packages/requests/models.py", line 605, in send
raise ConnectionError(e)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='umaurlquenaoapontapranada.com', port=80): Max retries exceeded with url: /
Veja a lista de possíveis códigos de status HTTP em: http://pt.wikipedia.org/wiki/Anexo:Listadecódigosdestatus_HTTP.
Obtendo um recurso com parâmetros
Quando queremos fazer uma requisição a um recurso na web usando um navegador, é comum passarmos alguns parâmetros na própria URL, através de uma requisição HTTP usando o método GET. Por exemplo, para fazer uma busca no Google, devemos passar um parâmetro q para http://www.google.com/search. Para passar o parâmetro via URL basta adicionar um ? ao final e então adicionar os parâmetros e valores ligados por =. Se passarmos mais de um parâmetro, devemos separá-los por &. Veja um exemplo:
http://www.uma.url.qualquer.com/recurso?parametro1=valor1¶metro2=valor2&maiscoisa=continua
Então, para soliciarmos uma busca ao google.com, podemos fazer uma requisição GET à URL:
http://www.google.com/search?q=o+que+quisermos+pesquisar
Podemos passar os parâmetros para a URL através de um dicionário que passamos como entrada à função requests.get(). O dicionário possui o seguinte formato:
{'nome do parametro 1': 'valor do parâmetro 1', 'nome do parâmetro 2': 'valor do parâmetro 2'}
Vamos fazer então uma busca no Google:
>>> response = requests.get("http://www.google.com/search", params={'q': 'busca qualquer coisa'})
>>> print response.status_code == 200
True
A página HTML que nosso browser iria renderizar se fosse ele o cliente da requisição é então armazenada no atributo response.content. Se você der uma observada no conteúdo desse atributo, verá que não parece nada fácil tirar algo útil dali, pois há uma quantidade enorme de ruído em meio à informação. Em outro post veremos como filtrar os dados de forma a “pegar” somente a parte útil da resposta, ignorando o HTML e outros códigos que vem junto com a resposta.
Acesso com autenticação básica
Alguns recursos que queremos acessar exigem uma autenticação HTTP para liberar o acesso. Como por exemplo, tente acessar a seguinte URL: http://httpbin.org/basic-auth/user/passwd. O navegador irá lhe confrontar com a seguinte tela, solicitando as suas credenciais:
Para passar os dados de usuário e senha com a requisição HTTP que estivermos fazendo, basta passsar um parâmetro chamado auth junto com a requisição. Primeiramente, vamos fazer uma requisição sem passar as credenciais:
>>> r = requests.get("http://httpbin.org/basic-auth/user/passwd")
>>> print r.status_code
401
O código 401 indica que a requisição não pode ser completada porque as credenciais de acesso estão incorretas. Agora vamos passar as credencias corretas (nome de usuário é 'user' e a senha é 'passwd'):
>>> r = requests.get("http://httpbin.org/basic-auth/user/passwd", auth=('user', 'passwd'))
>>> print r.status_code
200
Perceba que auth é um parâmetro que recebe uma tupla com os dados do usuário a ser autenticado.
O método POST
O método GET do protocolo HTTP é usado para a obtenção de dados de algum servidor web. Mas, se quisermos que nosso programa envie dados para algum servidor, devemos utilizar o método POST do HTTP.
Fazer requisições POST em um código Python nos permite inúmeras possibilidades, como por exemplo o preenchimento e submissão automática de formulários na web. Vamos testar o post em um serviço de testes, o httpbin:
>>> r = requests.post('http://httpbin.org/post', data={'comentario': 'huaaaaaaa'})
>>> print r.status_code
200
>>> print r.content
{
"origin": "xxx.xxx.xxx.xxx",
"files": {},
"form": {
"comentario": "huaaaaaaa"
},
"url": "http://httpbin.org/post",
"args": {},
"headers": {
"Content-Length": "20",
"Via": "1.0 PROXY",
"Accept-Encoding": "identity, deflate, compress, gzip",
"Connection": "close",
"Accept": "*/*",
"User-Agent": "python-requests/0.12.1",
"Host": "httpbin.org",
"Cache-Control": "max-age=259200",
"Content-Type": "application/x-www-form-urlencoded"
},
"json": null,
"data": ""
}
Conseguimos fazer a requisição e recebemos como resposta um recurso que se parece com um dicionário, mas que na verdade é um conteúdo codificado como JSON, que é um padrão para codificação de objetos para troca de mensagens pela rede (o JSON também será visto em um post futuro).
Um exemplo funcional
No início do post, acessamos o reddit.com usando o requests e obtivemos como resposta um monte de código HTML misturado com o conteúdo que nos interessa. Para quem não conhece, o reddit é um agregador de notícias submetidas e votadas pelos seus usuários. Com o slogan “the front page of the internet”, o reddit possui várias categorias e nelas são listadas as principais notícias/artigos do dia. Sabendo disso, vou mostrar um programinha bem simples e tosco que imprime na tela a lista de links da categoria programming do reddit:
import requests
def cria_lista_links(content):
links = []
for line in content.split('</p>'):
index = line.find('class="title ')
if index != -1:
href_start = line.find('href="', index) + 6
href_end = line.find('"', href_start)
links.append(line[href_start:href_end])
return links
r = requests.get("http://www.reddit.com/r/programming")
print '\n'.join(cria_lista_links(r.content))
IMPORTANTE: o código acima não é um exemplo de boas práticas!
O código acima busca o conteúdo HTML e percorre esse conteúdo verificando em cada linha se ela possui o texto 'class="title ', o que indica que a linha é um link. Depois, extraímos a URL de cada link e adicionamos à lista de resultado.
Como você pode ver, é bem fácil fazer esse trabalho de filtragem. Basta um pouquinho de paciência, ler o código HTML e descobrir padrões que possam ser buscados para fazer a filtragem. PORÉM, o código acima está longe de ser a melhor solução para o problema. Em um post futuro, veremos a forma correta de “filtrar” e extrair informações úteis de conteúdo HTML, usando um módulo específico para isso. Mas, o exemplo acima foi apresentado justamente para lhe mostrar que você já tem conhecimento suficiente para fazer o seu próprio programinha para filtrar dados das páginas que você gosta de acessar.
Vá em frente e se tiver dúvidas, comente aqui!
12 comentários sobre “Acessando recursos na web com Python”
Deixe um comentário
Você precisa fazer o login para publicar um comentário.


Gostei muito do tutorial é exatamente o que preciso mas tenho um problema, a rede da minha empresa utiliza um proxy ” file://c:/apl/proxy.pac ” como contorno isso? Nenhum dos exemplos eu consegui implementar…
Olá Rodrigo, qual é o seu sistema operacional? O correto seria alterar as configurações globais de rede do SO para usar o proxy. Você tem as configurações do proxy acima no browser, certo?
Obrigado pela resposta rápida. Uso o windows 7 professional pack 1. Meu proxy atual é configurado direto no browser indicando a pasta file://c:/apl/proxy.pac que tem o seguinte conteúdo:
proxy = “PROXY 10.4.3.91:3128”;
Depois que você postou eu achei outro post que ensinou a colocar o proxy no windows:
netsh winhttp set proxy 10.4.3.91:3128
Porém quando eu tento executar algum exemplo aparece a mensagem de erro:
ConnectionError: HTTPConnectionPool(host=’www.google.com’, port=80): Max retries exceeded with url: /umrecursoinvalido (Caused by : [Errno 10060] Uma tentativa de conexão falhou porque o componente conectado não respondeu
corretamente após um período de tempo ou a conexão estabelecida falhou
porque o host conectado não respondeu)
Rodrigo, o problema ali é que coloquei uma URL fictícia que vai dar erro mesmo. Normalmente o google retornaria um erro 404 (recurso não encontrado), mas como você está atrás de um proxy, o erro foi retornado pelo próprio proxy.
Tente substituir “www.google.com/umrecursoinvalido” por “www.google.com”. Deve funcionar.
Agora funcionou, já estou conseguindo receber dados de um equipamento, agora vou tratá-los e estudar um meio de automatizar o processo, muito obrigado.
Boa tarde Valdir,
Testei uma parte do código que funcionou com um endereço de intranet de um equipamento que me retornou uma tabela:
from datetime import datetime
import requests
response = requests.get(‘http://10.100.193.142/dados.js’)
print response.content
Quando eu troco o endereço por :
response = requests.get(‘http://www.google.com’)
me retorna o erro:
ConnectionError: HTTPConnectionPool(host=’www.google.com’, port=80): Max retries exceeded with url: / (Caused by : [Errno 10060] Uma tentativa de conexão falhou porque o componente conectado não respondeu
corretamente após um período de tempo ou a conexão estabelecida falhou
porque o host conectado não respondeu)
Achei que fosse o proxy mas eu mudei no cmd para:
netsh winhttp set proxy 10.4.3.91:3128 e o erro mencionado acima continua, tens ideia do que podes ser?
Ótimo Post, isso erra exatamente o que eu queria, fazer uma requisição automática que usa POST no formulário. E com Python melhor ainda.
🙂
Boa noite estou usando request para enviar informaçoes de uma estação metereologica mas nao consigo enviar os dados de uma variavel, alguem pode dizer como faço?
deste jeito o sistema entende como ok, mas preciso enviar o conteudo de variaveis.
payload = {‘tempf’:’65’,
‘rainin’:’0′,
‘barom’:’24.00′,
‘humidity’:’50’,
‘action’:’ updateraw’
}
preciso que seja deste jeito, mas as variaveis estão indo como string
payload = {‘tempf’:’TEMPERATURA’,
‘rainin’:’CHUVA’,
‘barom’:’PRESSAO’,
‘humidity’:’HUMIDADE’,
‘action’:’ atualizar’
}