Como buscar recursos da Internet
usando o pacote urllib
Release 3.13.7
Guido van Rossum and the Python development team
setembro 02, 2025
Python Software Foundation
Email: docs@[Link]
Sumário
1 Introdução 1
2 Acessando URLs 2
2.1 Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Cabeçalhos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3 Tratamento de exceções 4
3.1 URLError . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3.2 HTTPError . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.3 Resumindo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
4 info e geturl 6
5 Abridores e tratadores 7
6 Autenticação básica 7
7 Proxies 8
8 Socekts e camadas 9
9 Notas de rodapé 9
Índice 10
Autor
Michael Foord
1 Introdução
Related Articles
Você també m pode achar ú til o seguinte artigo na busca de recursos da web com Python:
1
• Autenticaçã o Bá sica
Um tutorial sobre Autenticação Básica, com exemplos em Python.
[Link] é um modulo Python para buscar URLs (Uniform Resource Locators). Ele oferece uma interface
muito simples, na forma da funçã o urlopen. Este é capaz de buscar URLs usando uma variedade de diferentes
protocolos. Ele també m oferece uma interface um pouco mais complexa para lidar com situaçõ es comuns - como
autenticaçã o bá sica, cookies, proxies e assim por diante. Estes sã o fornecidos por objetos chamados handlers (ma-
nipuladores) e openers (abridores).
[Link] suporta o acesso a URLs por meio de vá rios “esquemas de URL” (identificados pela string antes de
":" na URL - por exemplo "ftp" é o esquema de URL em "[Link] usando o protocolo de rede
associado a ele (como FTP e HTTP). Este tutorial foca no caso mais comum, HTTP.
Para situaçõ es simples “urlopen” é muito fá cil de usar. Mas assim que você se depara com erros ou casos nã o triviais
ao abrir URLs HTTP, você vai precisar entender um pouco mais do HyperText Transfer Protocol. A literatura
de referê ncia mais reconhecida e compreensível para o HTTP é RFC 2616. Ela é um documento té cnico e nã o
foi feita para ser fá cil de ler. Este documento busca ilustrar o uso de urllib com detalhes suficientes sobre HTTP
para te permitir seguir adiante. Ele nã o tem a intençã o de substituir a documentaçã o do [Link], mas é
suplementar a ela.
2 Acessando URLs
O modo mais simples de usar [Link] é o seguinte:
import [Link]
with [Link]('[Link] as response:
html = [Link]()
Se você deseja obter um recurso via URL e guardá -lo em uma localizaçã o temporá ria, você pode fazê -lo com as
funçõ es [Link]() e [Link]():
import shutil
import tempfile
import [Link]
with [Link]('[Link] as response:
with [Link](delete=False) as tmp_file:
[Link](response, tmp_file)
with open(tmp_file.name) as html:
pass
Muitos usos de urllib sã o simples assim (repare que ao invé s de uma URL ‘http:’ nó s poderíamos ter usado uma string
URL começando com ‘ftp:’, ‘file:’, etc.).. No entanto, o propó sito deste tutorial é explicar casos mais complicados,
concentrando em HTTP.
HTTP é baseado em solicitaçõ es (requests) e respostas (responses) - o cliente faz solicitaçõ es e os servidores mandam
respostas. [Link] espelha isto com um objeto Request que representa a solicitaçã o HTTP que você está
fazendo. Na sua forma mais simples, você cria um objeto Request que especifica a URL que você quer acessar.
Chamar urlopen com este objeto Request retorna um objeto de resposta para a URL solicitada. Essa resposta é um
objeto arquivo ou similar, o que significa que você pode, por exemplo, chamar .read() na resposta:
import [Link]
req = [Link]('[Link]
with [Link](req) as response:
the_page = [Link]()
2
Note que [Link] usa a mesma interface Request para tratar todos os esquemas URL. Por exemplo, você pode
fazer uma solicitaçã o FTP da seguinte forma:
req = [Link]('[Link]
No caso do HTTP, há duas coisas extras que os objetos Request permitem que você faça: primeiro, você pode passar
dados a serem enviados ao servidor. Segundo, você pode passar informaçõ es extras (“metadados”) sobre os dados
ou sobre a pró pria solicitaçã o para o servidor — essas informaçõ es sã o enviadas como “cabeçalhos” HTTP. Vamos
analisar cada um deles separadamente.
2.1 Dados
Às vezes, você deseja enviar dados para uma URL (geralmente a URL se refere a um script CGI (Common Gateway
Interface) ou outra aplicaçã o web). Com HTTP, isso geralmente é feito usando o que é conhecido como uma soli-
citaçã o POST. Isso geralmente é o que seu navegador faz quando você envia um formulá rio HTML preenchido na
web. Nem todos os POSTs precisam vir de formulá rios: você pode usar um POST para transmitir dados arbitrá rios
para sua pró pria aplicaçã o. No caso comum de formulá rios HTML, os dados precisam ser codificados de forma
padrã o e, em seguida, passados para o objeto Request como o argumento data. A codificaçã o é feita usando uma
funçã o da biblioteca [Link].
import [Link]
import [Link]
url = '[Link]
values = {'name' : 'Michael Foord',
'location' : 'Northampton',
'language' : 'Python' }
data = [Link](values)
data = [Link]('ascii') # data should be bytes
req = [Link](url, data)
with [Link](req) as response:
the_page = [Link]()
Observe que outras codificaçõ es à s vezes sã o necessá rias (por exemplo, para envio de arquivos de formulá rios HTML
- consulte HTML Specification, Form Submission para mais detalhes).
Se você nã o passar o argumento data, o urllib usará uma requisiçã o GET. Uma diferença entre requisiçõ es GET
e POST é que as requisiçõ es POST frequentemente tê m “efeitos colaterais”: elas alteram o estado do sistema de
alguma forma (por exemplo, ao fazer um pedido ao site para que cem libras de spam enlatado sejam entregues em
sua porta). Embora o padrã o HTTP deixe claro que os POSTs devem sempre causar efeitos colaterais, e as requisiçõ es
GET nunca causar efeitos colaterais, nada impede que uma requisiçã o GET tenha efeitos colaterais, nem que uma
requisiçã o POST nã o tenha efeitos colaterais. Dados també m podem ser passados em uma requisiçã o HTTP GET
codificando-os na pró pria URL.
Isso é feito como abaixo:
>>> import [Link]
>>> import [Link]
>>> data = {}
>>> data['name'] = 'Somebody Here'
>>> data['location'] = 'Northampton'
>>> data['language'] = 'Python'
>>> url_values = [Link](data)
>>> print(url_values) # The order may differ from below.
name=Somebody+Here&language=Python&location=Northampton
>>> url = '[Link]
>>> full_url = url + '?' + url_values
>>> data = [Link](full_url)
3
Observe que o URL completo é criado adicionando um ? ao URL, seguido pelos valores codificados.
2.2 Cabeçalhos
Discutiremos aqui um cabeçalho HTTP específico para ilustrar como adicionar cabeçalhos à sua solicitaçã o HTTP.
Alguns sites1 nã o gostam de ser navegados por programas ou enviam versõ es diferentes para navegadores diferen-
tes2 . Por padrã o, urllib se identifica como Python-urllib/x.y (onde x e y sã o os nú meros de versã o principal e
secundá ria da versã o do Python, por exemplo, Python-urllib/2.5), o que pode confundir o site ou simplesmente
nã o funcionar. A forma como um navegador se identifica é atravé s do cabeçalho User-Agent3 . Ao criar um objeto
Request, você pode passar um dicioná rio de cabeçalhos. O exemplo a seguir faz a mesma solicitaçã o acima, mas se
identifica como uma versã o do Internet Explorer4 .
import [Link]
import [Link]
url = '[Link]
user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)'
values = {'name': 'Michael Foord',
'location': 'Northampton',
'language': 'Python' }
headers = {'User-Agent': user_agent}
data = [Link](values)
data = [Link]('ascii')
req = [Link](url, data, headers)
with [Link](req) as response:
the_page = [Link]()
A resposta també m possui dois mé todos ú teis. Veja a seçã o sobre info e geturl, que vem depois de analisarmos o que
acontece quando as coisas dã o errado.
3 Tratamento de exceções
urlopen levanta URLError quando nã o consegue tratar uma resposta (embora, como de costume com APIs Python,
exceçõ es embutidas como ValueError, TypeError etc. també m possam ser levantadas).
HTTPError é a subclasse de URLError levantada no caso específico de URLs HTTP.
As classes de exceçã o sã o exportadas do mó dulo [Link].
3.1 URLError
Frequentemente, URLError é levantada porque nã o há conexã o de rede (nenhuma rota para o servidor especificado)
ou o servidor especificado nã o existe. Nesse caso, a exceçã o gerada terá um atributo “reason”, que é uma tupla
contendo um có digo de erro e uma mensagem de erro em texto.
Por exemplo
>>> req = [Link]('[Link]
>>> try: [Link](req)
... except [Link] as e:
... print([Link])
...
(4, 'getaddrinfo failed')
1 Google, por exemplo.
2 A detecçã o de navegadores é uma prá tica muito ruim para o design de sites; construir sites usando padrõ es web é muito mais sensato.
Infelizmente, muitos sites ainda enviam versõ es diferentes para navegadores diferentes.
3 O user agent para MSIE 6 é ‘Mozilla/4.0 (compatível; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)’
4 Para obter detalhes sobre mais cabeçalhos de solicitaçã o HTTP, consulte Referência rápida para cabeçalhos HTTP.
4
3.2 HTTPError
Cada resposta HTTP do servidor conté m um “có digo de status” numé rico. Às vezes, o có digo de status indica que
o servidor nã o consegue atender à solicitaçã o. Os manipuladores padrã o lidarã o com algumas dessas respostas para
você (por exemplo, se a resposta for um “redirecionamento” que solicita que o cliente busque o documento de uma
URL diferente, o urllib cuidará disso para você ). Para aquelas que ele nã o consegue tratar, o urlopen lançará um
HTTPError. Erros típicos incluem ‘404’ (pá gina nã o encontrada), ‘403’ (solicitaçã o proibida) e ‘401’ (autenticaçã o
necessá ria).
Veja a seçã o 10 de RFC 2616 para uma referê ncia sobre todos os có digos de erro HTTP.
A instâ ncia HTTPError levantada terá um atributo inteiro ‘code’, que corresponde ao erro enviado pelo servidor.
Códigos de erro
Como os tratadores padrã o controlam redirecionamentos (có digos no intervalo 300) e có digos no intervalo 100-299
indicam sucesso, normalmente você verá apenas có digos de erro no intervalo 400-599.
[Link] é um dicioná rio ú til de có digos de resposta que mostra
todos os có digos de resposta usados por RFC 2616. Um trecho do dicioná rio é mostrado abaixo
responses = {
...
<[Link]: 200>: ('OK', 'Request fulfilled, document follows'),
...
<[Link]: 403>: ('Forbidden',
'Request forbidden -- authorization will '
'not help'),
<HTTPStatus.NOT_FOUND: 404>: ('Not Found',
'Nothing matches the given URI'),
...
<HTTPStatus.IM_A_TEAPOT: 418>: ("I'm a Teapot",
'Server refuses to brew coffee because '
'it is a teapot'),
...
<HTTPStatus.SERVICE_UNAVAILABLE: 503>: ('Service Unavailable',
'The server cannot process the '
'request due to a high load'),
...
}
Quando um erro é levantado, o servidor responde retornando um có digo de erro HTTP e uma pá gina de erro. Você
pode usar a instâ ncia HTTPError como resposta na pá gina retornada. Isso significa que, alé m do atributo code, ela
també m possui os mé todos read, geturl e info, conforme retornados pelo mó dulo [Link]:
>>> req = [Link]('[Link]
>>> try:
... [Link](req)
... except [Link] as e:
... print([Link])
... print([Link]())
...
404
b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"[Link]
...
<title>Page Not Found</title>\n
...
5
3.3 Resumindo
Entã o, se você quiser se preparar para HTTPError ou URLError, existem duas abordagens bá sicas. Eu prefiro a
segunda.
Número 1
from [Link] import Request, urlopen
from [Link] import URLError, HTTPError
req = Request(someurl)
try:
response = urlopen(req)
except HTTPError as e:
print('The server couldn\'t fulfill the request.')
print('Error code: ', [Link])
except URLError as e:
print('We failed to reach a server.')
print('Reason: ', [Link])
else:
# tudo certo
® Nota
O except HTTPError deve vir primeiro, caso contrá rio, except URLError também capturará uma
HTTPError.
Número 2
from [Link] import Request, urlopen
from [Link] import URLError
req = Request(someurl)
try:
response = urlopen(req)
except URLError as e:
if hasattr(e, 'reason'):
print('We failed to reach a server.')
print('Reason: ', [Link])
elif hasattr(e, 'code'):
print('The server couldn\'t fulfill the request.')
print('Error code: ', [Link])
else:
# tudo certo
4 info e geturl
A resposta retornada por urlopen (ou a instâ ncia HTTPError) tem dois mé todos ú teis info() e geturl() e é
definida no mó dulo [Link].
• geturl - Isso retorna a URL real da pá gina recuperada. Isso é ú til porque urlopen (ou o objeto de abertura
utilizado) pode ter seguido um redirecionamento. A URL da pá gina recuperada pode nã o ser a mesma que a
URL solicitada.
• info - Isso retorna um objeto semelhante a um dicioná rio que descreve a pá gina recuperada, particularmente
os cabeçalhos enviados pelo servidor. Atualmente, é uma instâ ncia de [Link].
Cabeçalhos típicos incluem ‘Content-length’, ‘Content-type’ e assim por diante. Consulte a “Referê ncia rá pida para
6
cabeçalhos HTTP <[Link] para obter uma lista ú til de cabeçalhos HTTP com breves expli-
caçõ es sobre seu significado e uso.
5 Abridores e tratadores
Ao buscar uma URL, você usa um abridor (uma instâ ncia do talvez confuso nome [Link].
OpenerDirector). Normalmente, usamos o abridor padrã o - via urlopen -, mas você pode criar abridores
personalizados. Os abridores usam manipuladores. Todo o “trabalho pesado” é feito pelos manipuladores. Cada
manipulador sabe como abrir URLs para um esquema de URL específico (http, ftp, etc.) ou como lidar com um
aspecto da abertura de URL, por exemplo, redirecionamentos HTTP ou cookies HTTP.
Você vai querer criar abridores se quiser buscar URLs com manipuladores específicos instalados, por exemplo, para
obter um abridor que manipule cookies ou para obter um abridor que nã o manipule redirecionamentos.
Para criar um abridor, instancie um OpenerDirector e entã o chame .
add_handler(some_handler_instance) repetidamente.
Como alternativa, você pode usar build_opener, que é uma funçã o conveniente para criar objetos de abertura com
uma ú nica chamada de funçã o. build_opener adiciona vá rios tratadores por padrã o, mas fornece uma maneira
rá pida de adicionar mais e/ou substituir os tratadores padrã o.
Outros tipos de manipuladores que você pode querer podem lidar com proxies, autenticaçã o e outras situaçõ es co-
muns, mas um pouco especializadas.
install_opener pode ser usado para tornar um objeto opener o abridor padrã o (global). Isso significa que
chamadas para urlopen usarã o o abridor que você instalou.
Objetos abridores tê m um mé todo open, que pode ser chamado diretamente para buscar URLs da mesma forma que
a funçã o urlopen: nã o há necessidade de chamar install_opener, exceto por conveniê ncia.
6 Autenticação básica
Para ilustrar a criaçã o e instalaçã o de um manipulador, usaremos o HTTPBasicAuthHandler. Para uma discussã o
mais detalhada sobre este assunto — incluindo uma explicaçã o de como funciona a autenticaçã o bá sica — consulte
este tutorial de autenticaçã o bá sica.
Quando a autenticaçã o é necessá ria, o servidor envia um cabeçalho (e o có digo de erro 401) solicitando autenticaçã o.
Isso especifica o esquema de autenticaçã o e um “domínio”. O cabeçalho se parece com: WWW-Authenticate:
SCHEME realm="REALM".
Por exemplo:
WWW-Authenticate: Basic realm="cPanel Users"
O cliente deve entã o tentar a solicitaçã o novamente com o nome e a senha apropriados para o domínio incluídos como
cabeçalho na solicitaçã o. Isso é “autenticaçã o bá sica”. Para simplificar esse processo, podemos criar uma instâ ncia
de HTTPBasicAuthHandler e um opener para usar esse manipulador.
O HTTPBasicAuthHandler usa um objeto chamado gerenciador de senhas para manipular o mapeamento de URLs
e domínios para senhas e nomes de usuá rio. Se você souber qual é o domínio (a partir do cabeçalho de autenticaçã o
enviado pelo servidor), poderá usar um HTTPPasswordMgr. Frequentemente, nã o importa qual seja o domínio.
Nesse caso, é conveniente usar HTTPPasswordMgrWithDefaultRealm. Isso permite que você especifique um
nome de usuá rio e uma senha padrã o para uma URL. Isso será fornecido caso você nã o forneça uma combinaçã o
alternativa para um domínio específico. Indicamos isso fornecendo None como argumento de domínio para o mé todo
add_password.
A URL de nível superior é a primeira URL que requer autenticaçã o. URLs “mais profundas” que a URL que você
passa para .add_password() també m corresponderã o.
# cria um gerenciador de senhas
password_mgr = [Link]()
(continua na pró xima pá gina)
7
(continuaçã o da pá gina anterior)
# Adiciona o nome de usuário e senha.
# Se soubéssemos o realm, poderíamos usá-lo em vez de None.
top_level_url = "[Link]
password_mgr.add_password(None, top_level_url, username, password)
handler = [Link](password_mgr)
# cria um "opener" (OpenerDirector instance)
opener = [Link].build_opener(handler)
# usa o opener para obter uma URL
[Link](a_url)
# Instala o opener.
# Agora, todas as chamadas a [Link] usam nosso opener.
[Link].install_opener(opener)
® Nota
No exemplo acima, fornecemos apenas nosso HTTPBasicAuthHandler para build_opener. Por padrã o,
os “openers” possuem os manipuladores para situaçõ es normais: ProxyHandler (se uma configuraçã o de
proxy, como uma variá vel de ambiente http_proxy, estiver definida), UnknownHandler, HTTPHandler,
HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler, DataHandler,
HTTPErrorProcessor.
top_level_url é , na verdade, ou uma URL completa (incluindo o componente do esquema ‘http:’, o nome do
host e, opcionalmente, o nú mero da porta), por exemplo, "[Link] ou uma “autoridade” (ou
seja, o nome do host, incluindo, opcionalmente, o nú mero da porta), por exemplo, "[Link]" ou "example.
com:8080" (este ú ltimo exemplo inclui um nú mero de porta). A autoridade, se presente, NÃO deve conter o
componente “userinfo” - por exemplo, "joe:senha@[Link]" nã o está correto.
7 Proxies
urllib detectará automaticamente suas configuraçõ es de proxy e as utilizará . Isso ocorre por meio do
ProxyHandler, que faz parte da cadeia de manipuladores normal quando uma configuraçã o de proxy é detec-
tada. Normalmente, isso é bom, mas há ocasiõ es em que pode nã o ser ú til5 . Uma maneira de fazer isso é configurar
nosso pró prio ProxyHandler, sem proxies definidos. Isso é feito seguindo etapas semelhantes à configuraçã o de
um manipulador de autenticaçã o bá sica:
>>> proxy_support = [Link]({})
>>> opener = [Link].build_opener(proxy_support)
>>> [Link].install_opener(opener)
® Nota
Atualmente, [Link] não oferece suporte à busca de locais https por meio de um proxy. No entanto,
isso pode ser habilitado estendendo [Link], conforme mostrado na receita6 .
5 No meu caso, preciso usar um proxy para acessar a internet no trabalho. Se você tentar buscar URLs localhost por meio desse proxy, ele
as bloqueia. O IE está configurado para usar o proxy, que o urllib detecta. Para testar scripts com um servidor localhost, preciso impedir que o
urllib use o proxy.
6 Abridor urllib para proxy SSL (mé todo CONNECT): Receita do livro de receitas ASPN.
8
® Nota
HTTP_PROXY será ignorado se uma variá vel REQUEST_METHOD estiver definida; veja a documentaçã o em
getproxies().
8 Socekts e camadas
O suporte do Python para buscar recursos web é em camadas. urllib usa a biblioteca [Link], que por sua vez
usa a biblioteca de sockets.
A partir do Python 2.3, você pode especificar quanto tempo um soquete deve aguardar por uma resposta antes de
atingir o tempo limite. Isso pode ser ú til em aplicaçõ es que precisam buscar pá ginas web. Por padrã o, o mó dulo
socket não tem tempo limite e pode travar. Atualmente, o tempo limite do soquete nã o é exposto nos níveis [Link]
ou [Link]. No entanto, você pode definir o tempo limite padrã o globalmente para todos os soquetes usando
import socket
import [Link]
# tempo limite em secungos
timeout = 10
[Link](timeout)
# isso chamada a [Link] agora usa o tempo limite padrão
# que nós definidos no módulo socket
req = [Link]('[Link]
response = [Link](req)
9 Notas de rodapé
Este documento foi revisado e revisado por John Lee.
9
Índice
R
RFC
RFC 2616, 2, 5
10