>  기사  >  백엔드 개발  >  Python urllib2에 대한 자세한 설명과 예제

Python urllib2에 대한 자세한 설명과 예제

高洛峰
高洛峰원래의
2016-10-18 09:10:051211검색

urllib2는 URL(Uniform Resource Locator)을 얻는 Python의 구성 요소입니다. 이는 urlopen 함수 형태로 매우 간단한 인터페이스를 제공합니다.

이는 다양한 프로토콜을 사용하여 URL을 얻는 기능도 있으며 기본 확인, 쿠키와 같은 일반적인 상황을 처리하기 위한 보다 복잡한 인터페이스도 제공합니다. , 프록시 및 기타.

핸들러와 오프너 객체를 통해 제공됩니다.

urllib2는 관련 네트워크 프로토콜을 사용하는 다양한 형식(URL에서 ":" 앞에 정의된 문자열, 예: "ftp"는 "ftp:python.ort/"의 접두사)으로 URL을 얻는 것을 지원합니다. (FTP, HTTP 등)

획득합니다. 이 튜토리얼은 가장 널리 사용되는 애플리케이션인 HTTP에 중점을 둡니다.

간단한 애플리케이션의 경우 urlopen을 사용하는 것이 매우 쉽습니다. 그러나 HTTP URL을 열 때 오류나 예외가 발생하는 경우 HTTP(Hypertext Transfer Protocol)에 대한 어느 정도 이해가 필요합니다.

가장 권위 있는 HTTP 문서는 물론 RFC 2616(http://rfc.net/rfc2616.html)입니다. 이 문서는 기술 문서이므로 읽기가 쉽지 않습니다. 이 HOWTO 튜토리얼의 목적은 urllib2

를 사용하는 방법을 보여주고 이해를 돕기 위한 충분한 HTTP 세부 정보를 제공하는 것입니다. urllib2의 문서는 아니지만 보조적인 역할을 합니다.

URL 가져오기

urllib2를 사용하는 가장 간단한 방법은 다음과 같습니다.

import urllib2 
response = urllib2.urlopen('http://python.org/') 
html = response.read()

urllib2의 많은 애플리케이션은 다음과 같습니다. 단순합니다("http:" 외에도 URL을 "ftp:", "file:" 등으로 대체할 수 있음을 기억하세요). 그러나 이 기사에서는 HTTP의 더 복잡한 응용을 가르칩니다.

HTTP는 요청 및 응답 메커니즘을 기반으로 합니다. 즉, 클라이언트가 요청하고 서버가 응답을 제공합니다. urllib2는 요청 객체를 사용하여 HTTP 요청을 매핑합니다. 가장 간단한 사용 형태에서는 urlopen을 호출하고 요청 객체를 전달하여 요청하려는

주소로 요청 객체를 생성합니다. 관련 요청 응답 객체를 반환합니다. 이 응답 객체는 파일 객체와 유사하므로 응답에서 .read()를 호출할 수 있습니다.

import urllib2 
req = urllib2.Request('http://www.pythontab.com') 
response = urllib2.urlopen(req) 
the_page = response.read()

urllib2는 모든 URL 헤더를 처리하기 위해 동일한 인터페이스를 사용한다는 점을 기억하세요. 예를 들어 아래와 같이 ftp 요청을 생성할 수 있습니다.

req = urllib2.Request('ftp://example.com/')

HTTP 요청을 할 때 두 가지 추가 작업을 수행할 수 있습니다. 첫째, 데이터 양식 데이터를 보낼 수 있고, 둘째, 데이터 또는 자체에 대한 추가 정보("메타데이터")를 서버에 보낼 수 있습니다. 이 데이터는 HTTP "헤더"로 전송됩니다.

이것이 어떻게 전송되는지 살펴보겠습니다.

데이터 데이터

때때로 일부 데이터를 URL로 보내고 싶을 때가 있습니다(일반적으로 URL은 CGI [Common Gateway Interface] 스크립트 또는 기타 웹 애플리케이션에 연결되어 있습니다). HTTP에서는 잘 알려진 POST 요청을 사용하여 전송되는 경우가 많습니다. 이는 일반적으로 HTML 양식을 제출할 때 브라우저에서 수행됩니다.

모든 POST가 양식에서 생성되는 것은 아닙니다. POST를 사용하여 임의의 데이터를 자신의 프로그램에 제출할 수 있습니다. 일반 HTML 양식의 경우 데이터를 표준 형식으로 인코딩해야 합니다. 그런 다음 이를 데이터 매개변수로 Request 객체에 전달합니다. 인코딩은 urllib2 대신 urllib 함수를 사용하여 작동합니다.

import urllib 
import urllib2 
url = 'http://www.pythontab.com' 
values = {'name' : 'Michael Foord', 
          'location' : 'pythontab', 
          'language' : 'Python' } 
data = urllib.urlencode(values) 
req = urllib2.Request(url, data) 
response = urllib2.urlopen(req) 
the_page = response.read()

때로는 다른 인코딩이 필요하다는 점을 기억하세요(예: HTML에서 파일 업로드 - http://www.w3.org/TR/REC 참조 - html40/interact/forms.html#h-17.13 HTML 사양, 양식 제출에 대한 자세한 설명).

ugoni가 data 매개변수를 전송하지 않으면 urllib2는 GET 요청 방식을 사용합니다. GET 요청과 POST 요청의 차이점은 POST 요청에는 일반적으로 "부작용"이 있다는 것입니다. 즉, 어떤 방식으로든 시스템 상태를 변경합니다(예: 문에 쓰레기 더미를 제출하는 등).

HTTP 표준에서는 일반적으로 POST에는 부작용이 있고 GET 요청에는 부작용이 없다는 점을 분명히 하고 있지만 GET 요청에는 부작용이 있는 것을 방지할 수 있는 방법이 없으며 마찬가지로 POST 요청에는 부작용이 없을 수도 있습니다. Get 요청

에서 URL 자체를 인코딩하여 데이터를 전달할 수도 있습니다.

다음 예 참조

>>> import urllib2 
>>> import urllib 
>>> data = {} 
>>> data['name'] = 'Somebody Here' 
>>> data['location'] = 'pythontab' 
>>> data['language'] = 'Python' 
>>> url_values = urllib.urlencode(data) 
>>> print url_values 
name=blueelwang+Here&language=Python&location=pythontab 
>>> url = 'http://www.pythontab.com' 
>>> full_url = url + '?' + url_values 
>>> data = urllib2.open(full_url)

헤더

여기에서는 HTTP 요청에 헤더를 추가하는 방법을 설명하기 위해 특정 HTTP 헤더에 대해 논의하겠습니다.

프로그램에 의한 액세스(사람이 아닌 액세스)를 좋아하지 않거나 다른 버전의 콘텐츠를 다른 브라우저로 보내는 일부 사이트가 있습니다. 기본 urllib2는 자신을 "Python-urllib/x.y"로 식별합니다(x와 y는 Python-urllib/2.5와 같은 Python 주 및 부 버전 번호입니다).

이 ID는 사이트를 혼란스럽게 하거나 단순히 작동하지 않습니다. 브라우저는 User-Agent 헤더를 통해 자신의 신원을 확인합니다. 요청 객체를 생성할 때 헤더 데이터가 포함된 사전을 제공할 수 있습니다. 아래 예는 위와 동일한 콘텐츠를 전송하지만 Internet Explorer로

자체를 에뮬레이트합니다.

import urllib 
import urllib2 
url = 'http://www.pythontab.com' 
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' 
  
values = {'name' : 'Michael Foord', 
          'location' : 'pythontab', 
          'language' : 'Python' } 
headers = { 'User-Agent' : user_agent } 
data = urllib.urlencode(values) 
req = urllib2.Request(url, data, headers) 
response = urllib2.urlopen(req) 
the_page = response.read()

응답 개체에도 두 가지 유용한 메서드가 있습니다. 아래의 info 및 geturl 섹션을 살펴보면 오류가 발생하면 어떤 일이 발생하는지 확인할 수 있습니다.

예외 처리 예외 처리

urlopen이 응답을 처리할 수 없으면 urlError가 생성됩니다(그러나 ValueError, TypeError 등과 같은 일반적인 Python API 예외도 동시에 생성됩니다). .

HTTPError는 일반적으로 특정 HTTP URL에서 생성되는 urlError의 하위 클래스입니다.

URL오류

通常,URLError在没有网络连接(没有路由到特定服务器),或者服务器不存在的情况下产生。这种情况下,异常同样会带有"reason"属性,它是一个tuple,包含了一个错误号和一个错误信息。

例如

>>> req = urllib2.Request('http://www.pythontab.com') 
>>> try: urllib2.urlopen(req) 
>>> except URLError, e: 
>>>    print e.reason 
>>>

   

(4, 'getaddrinfo failed') 

HTTPError

服务器上每一个HTTP 应答对象response包含一个数字"状态码"。有时状态码指出服务器无法完成请求。默认的处理器会为你处理一部分这种应答(例如:假如response是一个"重定向",需要客户端从别的地址获取文档

,urllib2将为你处理)。其他不能处理的,urlopen会产生一个HTTPError。典型的错误包含"404"(页面无法找到),"403"(请求禁止),和"401"(带验证请求)。

请看RFC 2616 第十节有所有的HTTP错误码

HTTPError实例产生后会有一个整型'code'属性,是服务器发送的相关错误号。

Error Codes错误码

因为默认的处理器处理了重定向(300以外号码),并且100-299范围的号码指示成功,所以你只能看到400-599的错误号码。

BaseHTTPServer.BaseHTTPRequestHandler.response是一个很有用的应答号码字典,显示了RFC 2616使用的所有的应答号。这里为了方便重新展示该字典。(译者略)

当一个错误号产生后,服务器返回一个HTTP错误号,和一个错误页面。你可以使用HTTPError实例作为页面返回的应答对象response。这表示和错误属性一样,它同样包含了read,geturl,和info方法。

>>> req = urllib2.Request('http://www.python.org/fish.html') 
>>> try: 
>>>     urllib2.urlopen(req) 
>>> except URLError, e: 
>>>     print e.code 
>>>     print e.read() 
>>>

    

404 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
    "http://www.w3.org/TR/html4/loose.dtd"> 
<?xml-stylesheet href="./css/ht2html.css" 
    type="text/css"?> 
<html><head><title>Error 404: File Not Found</title> 
...... etc...

   

Wrapping it Up包装

所以如果你想为HTTPError或URLError做准备,将有两个基本的办法。我则比较喜欢第二种。

第一个:

from urllib2 import Request, urlopen, URLError, HTTPError 
req = Request(someurl) 
try: 
    response = urlopen(req) 
except HTTPError, e: 
    print &#39;The server couldn/&#39;t fulfill the request.&#39; 
    print &#39;Error code: &#39;, e.code 
except URLError, e: 
    print &#39;We failed to reach a server.&#39; 
    print &#39;Reason: &#39;, e.reason 
else: 
    # everything is fine

   

注意:except HTTPError 必须在第一个,否则except URLError将同样接受到HTTPError。 

第二个:

from urllib2 import Request, urlopen, URLError 
req = Request(someurl) 
try: 
    response = urlopen(req) 
except URLError, e: 
    if hasattr(e, &#39;reason&#39;): 
        print &#39;We failed to reach a server.&#39; 
        print &#39;Reason: &#39;, e.reason 
    elif hasattr(e, &#39;code&#39;): 
        print &#39;The server couldn/&#39;t fulfill the request.&#39; 
        print &#39;Error code: &#39;, e.code 
else: 
    # everything is fine

info and geturl

urlopen返回的应答对象response(或者HTTPError实例)有两个很有用的方法info()和geturl()

geturl -- 这个返回获取的真实的URL,这个很有用,因为urlopen(或者opener对象使用的)或许

会有重定向。获取的URL或许跟请求URL不同。

info -- 这个返回对象的字典对象,该字典描述了获取的页面情况。通常是服务器发送的特定头headers。目前是httplib.HTTPMessage 实例。

经典的headers包含"Content-length","Content-type",和其他。查看Quick Reference to HTTP Headers(http://www.cs.tut.fi/~jkorpela/http.html)

获取有用的HTTP头列表,以及它们的解释意义。

Openers和Handlers

当你获取一个URL你使用一个opener(一个urllib2.OpenerDirector的实例,urllib2.OpenerDirector可能名字可能有点让人混淆。)正常情况下,我们

使用默认opener -- 通过urlopen,但你能够创建个性的openers,Openers使用处理器handlers,所有的“繁重”工作由handlers处理。每个handlers知道

如何通过特定协议打开URLs,或者如何处理URL打开时的各个方面,例如HTTP重定向或者HTTP cookies。

如果你希望用特定处理器获取URLs你会想创建一个openers,例如获取一个能处理cookie的opener,或者获取一个不重定向的opener。

要创建一个 opener,实例化一个OpenerDirector,然后调用不断调用.add_handler(some_handler_instance).

同样,可以使用build_opener,这是一个更加方便的函数,用来创建opener对象,他只需要一次函数调用。

build_opener默认添加几个处理器,但提供快捷的方法来添加或更新默认处理器。

其他的处理器handlers你或许会希望处理代理,验证,和其他常用但有点特殊的情况。

install_opener 用来创建(全局)默认opener。这个表示调用urlopen将使用你安装的opener。

Opener对象有一个open方法,该方法可以像urlopen函数那样直接用来获取urls:通常不必调用install_opener,除了为了方便。

Basic Authentication 基本验证

为了展示创建和安装一个handler,我们将使用HTTPBasicAuthHandler,为了更加细节的描述本主题--包含一个基础验证的工作原理。

请看Basic Authentication Tutorial(http://www.voidspace.org.uk/python/articles/authentication.shtml)

当需要基础验证时,服务器发送一个header(401错误码) 请求验证。这个指定了scheme 和一个‘realm’,看起来像这样:Www-authenticate: SCHEME realm="REALM".

例如

Www-authenticate: Basic realm="cPanel Users"

客户端必须使用新的请求,并在请求头里包含正确的姓名和密码。这是“基础验证”,为了简化这个过程,我们可以创建一个HTTPBasicAuthHandler的实例,并让opener使用这个

handler。

HTTPBasicAuthHandler使用一个密码管理的对象来处理URLs和realms来映射用户名和密码。如果你知道realm(从服务器发送来的头里)是什么,你就能使用HTTPPasswordMgr。

通常人们不关心realm是什么。那样的话,就能用方便的HTTPPasswordMgrWithDefaultRealm。这个将在你为URL指定一个默认的用户名和密码。这将在你为特定realm提供一个其他组合时

得到提供。我们通过给realm参数指定None提供给add_password来指示这种情况。

最高层次的URL是第一个要求验证的URL。你传给.add_password()更深层次的URLs将同样合适。

# 创建一个密码管理者 
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm() 
# 添加用户名和密码 
# 如果知道 realm, 我们可以使用他代替 ``None``. 
top_level_url = "http://example.com/foo/" 
password_mgr.add_password(None, top_level_url, username, password) 
handler = urllib2.HTTPBasicAuthHandler(password_mgr) 
# 创建 "opener" (OpenerDirector 实例) 
opener = urllib2.build_opener(handler) 
# 使用 opener 获取一个URL 
opener.open(a_url) 
# 安装 opener. 
# 现在所有调用 urllib2.urlopen 将用我们的 opener. 
urllib2.install_opener(opener)

   

注意:以上的例子我们仅仅提供我们的HHTPBasicAuthHandler给build_opener。默认的openers有正常状况的handlers--ProxyHandler,UnknownHandler,HTTPHandler,HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler, HTTPErrorProcessor。

top_level_url 实际上可以是完整URL(包含"http:",以及主机名及可选的端口号)例如:http://example.com/,也可以是一个“authority”(即主机名和可选的

包含端口号)例如:“example.com” or “example.com:8080”(后者包含了端口号)。权限验证,如果递交的话不能包含"用户信息"部分,例如:

“joe@password:example.com”是错误的。

Proxies代理urllib 将自动监测你的代理设置并使用他们。这个通过ProxyHandler这个在正常处理器链中的对象来处理。通常,那工作的很好。但有时不起作用

。其中一个方法便是安装我们自己的代理处理器ProxyHandler,并不定义代理。这个跟使用Basic Authentication 处理器很相似。

>>> proxy_support = urllib.request.ProxyHandler({}) 
>>> opener = urllib.request.build_opener(proxy_support) 
>>> urllib.request.install_opener(opener)

   

注意:

此时urllib.request不支持通过代理获取https地址。但,这个可以通过扩展urllib.request达到目的。

Sockets and Layers

Python支持获取网络资源是分层结构。urllib 使用http.client库,再调用socket库实现。

在Python2.3你可以指定socket的等待回应超时时间。这个在需要获取网页的应用程序里很有用。默认的socket模型没有超时和挂起。现在,socket超时没有暴露

给http.client或者urllib.request层。但你可以给所有的sockets设置全局的超时。


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.