Maison >développement back-end >Tutoriel Python >Explication détaillée de l'utilisation de Python urllib2

Explication détaillée de l'utilisation de Python urllib2

巴扎黑
巴扎黑original
2017-09-04 13:40:171921parcourir

urllib2 est un composant de Python qui obtient des URL (Uniform Resource Locators). Il fournit une interface très simple sous la forme de la fonction urlopen, qui a la capacité d'obtenir des URL en utilisant différents protocoles. Il fournit également une interface plus complexe pour gérer des situations courantes, telles que : l'authentification de base, les cookies, les proxys et autres. Ils sont fournis via des objets gestionnaires et ouvreurs.

urllib2 prend en charge l'obtention d'URL dans différents formats (chaînes définies avant ":" dans l'URL, par exemple : "ftp" est le préfixe de "ftp:python.ort/"), qui utilisent leurs protocoles réseau associés (tels que FTP, HTTP) à obtenir. Ce didacticiel se concentre sur l'application la plus répandue : HTTP.

Pour des applications simples, urlopen est très simple à utiliser. Mais lorsque vous rencontrez des erreurs ou des exceptions lors de l'ouverture d'URL HTTP, vous aurez besoin d'une certaine compréhension du protocole HTTP (Hypertext Transfer Protocol).

Le document HTTP faisant le plus autorité est bien sûr le RFC 2616 (http://rfc.net/rfc2616.html). Il s'agit d'un document technique, il n'est donc pas facile à lire. Le but de ce tutoriel HOWTO est de montrer comment utiliser urllib2,

et de fournir suffisamment de détails HTTP pour vous aider à comprendre. Ce n'est pas une documentation de urllib2, mais joue un rôle auxiliaire.

Obtenir des URL

La façon la plus simple d'utiliser urllib2

Exemple de code :

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

De nombreuses applications d'urllib2 sont aussi simples (rappelez-vous, à l'exception de " http:", l'URL peut également être remplacée par "ftp:", "file:", etc.). Mais cet article enseigne des applications plus complexes de HTTP.

HTTP est basé sur le mécanisme de requête et de réponse : le client fait une requête et le serveur fournit une réponse. urllib2 utilise un objet Request pour mapper la requête HTTP que vous effectuez. Dans sa forme d'utilisation la plus simple, vous créerez un objet Request avec l'adresse que vous souhaitez demander. En appelant urlopen et en transmettant l'objet Request, un objet de réponse à la requête associé sera créé. être renvoyé. , cet objet de réponse est comme un objet fichier, vous pouvez donc appeler .read() dans Response.

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

N'oubliez pas que urllib2 utilise la même interface pour gérer tous les en-têtes d'URL. Par exemple, vous pouvez créer une requête FTP comme ci-dessous.

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

Vous permet de faire deux choses supplémentaires lors des requêtes HTTP. Premièrement, vous pouvez envoyer des données du formulaire de données, et deuxièmement, vous pouvez envoyer des informations supplémentaires sur les données ou elles-mêmes (« métadonnées ») au serveur. Ces données sont envoyées sous forme d'« en-têtes » HTTP.

Voyons comment ceux-ci sont envoyés.

Données de données

Parfois, vous souhaitez envoyer des données à une URL (généralement l'URL est connectée à un script CGI [Common Gateway Interface] ou à une autre application WEB). En HTTP, cela est souvent envoyé à l'aide de la célèbre requête POST. Cela est généralement effectué par votre navigateur lorsque vous soumettez un formulaire HTML.

Tous les POST ne proviennent pas de formulaires, vous pouvez utiliser POST pour soumettre des données arbitraires à votre propre programme. Pour les formulaires HTML généraux, les données doivent être codées dans un formulaire standard. Transmettez-le ensuite à l’objet Request en tant que paramètre de données. L'encodage fonctionne en utilisant les fonctions urllib au lieu de urllib2.

Exemples de code :

import urllib 
import urllib2 
url = 'http://www.php.cn' 
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()

N'oubliez pas que parfois d'autres encodages sont nécessaires (par exemple, télécharger des fichiers à partir de HTML - voir http://www.w3.org/TR/REC-html40/ interagir /forms.html#h-17.13 Spécification HTML, soumission de formulaire (description détaillée).

Si ugoni ne transmet pas le paramètre data, urllib2 utilise la méthode de requête GET. La différence entre les requêtes GET et POST est que les requêtes POST ont généralement des "effets secondaires", elles modifient l'état du système d'une manière ou d'une autre (comme soumettre un tas d'ordures à votre porte).

Bien que la norme HTTP indique clairement que les POST ont généralement des effets secondaires et que les requêtes GET n'en ont pas, rien n'empêche les requêtes GET d'avoir des effets secondaires, et de même, les requêtes POST peuvent ne pas avoir d'effets secondaires. Les données peuvent également être transmises en les codant dans l'URL elle-même dans la requête Get.

Exemple de code :

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

En-têtes

Nous discuterons ici des en-têtes HTTP spécifiques pour illustrer comment ajouter des en-têtes à vos requêtes HTTP.

Certains sites n'aiment pas être accessibles par des programmes (accès non humain) ou envoyer différentes versions de contenu à différents navigateurs. L'urllib2 par défaut s'identifie comme "Python-urllib/x.y" (x et y sont les numéros de version majeure et mineure de Python, comme Python-urllib/2.5). Cette identité peut confondre les sites, ou tout simplement ne pas fonctionner. Le navigateur confirme son identité via l'en-tête User-Agent. Lorsque vous créez un objet de requête, vous pouvez lui donner un dictionnaire contenant les données d'en-tête. L'exemple suivant envoie le même contenu que ci-dessus, mais s'émule

comme Internet Explorer.

import urllib 
import urllib2 
url = 'http://www.php.cn' 
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()

L'objet de réponse dispose également de deux méthodes utiles. En regardant les sections info et geturl ci-dessous, nous verrons ce qui se passe lorsqu'une erreur se produit.

Gérer les exceptions gérant les exceptions

Lorsque urlopen ne peut pas gérer une réponse, une urlError est générée (mais les exceptions courantes des API Python telles que ValueError, TypeError, etc. seront également générées en même temps) .

HTTPError est une sous-classe de urlError, généralement générée dans des URL HTTP spécifiques.

URLError

Habituellement, URLError se produit lorsqu'il n'y a pas de connexion réseau (pas de routage vers un serveur spécifique) ou que le serveur n'existe pas. Dans ce cas, l'exception aura également l'attribut "reason", qui est un tuple contenant un numéro d'erreur et un message d'erreur.

Par exemple

>>> req = urllib2.Request('http://www.php.cn') 
>>> 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.php.cn/fish.html') 
>>> try: 
>>>     urllib2.urlopen(req) 
>>> except URLError, e: 
>>>     print e.code 
>>>     print e.read() 
>>>
404 
 
 Error 404: File Not Found 
...... etc...

Wrapping it Up包装

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

第一个:

from urllib2 import Request, urlopen, URLError, HTTPError 
req = Request(someurl) 
try: 
    response = urlopen(req) 
except HTTPError, e: 
    print 'The server couldn/'t fulfill the request.' 
    print 'Error code: ', e.code 
except URLError, e: 
    print 'We failed to reach a server.' 
    print 'Reason: ', 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, 'reason'): 
        print 'We failed to reach a server.' 
        print 'Reason: ', e.reason 
    elif hasattr(e, 'code'): 
        print 'The server couldn/'t fulfill the request.' 
        print 'Error code: ', 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://php.cn/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设置全局的超时。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn