云南网站建设,企业信息化软件定制开发

专业提供昆明网站建设, 昆明软件开发, 云南网站建设,企业信息化软件定制开发服务免费咨询QQ932256355

博客园 首页 新随笔 联系 订阅 管理

Python 网络数据获取神器 urllib:从入门到精通教程

在 Python 编程中,urllib包是获取网络资源的重要工具。本文详细介绍urllib包的使用方法,涵盖从简单的 URL 资源获取,到处理数据传输、HTTP 头部信息、异常情况,再到OpenerHandler的高级应用,帮助读者全面掌握利用urllib进行网络数据获取的技能,解决实际编程中的相关问题。

一、概述

urllib.request是 Python 用于获取 URL(统一资源定位符)的模块,它提供了urlopen函数,支持通过多种协议获取 URL 资源。urllib.request支持多种 “URL 方案”,本教程聚焦最常用的 HTTP 场景。在使用urllib时,简单场景下urlopen很容易使用,但遇到 HTTP 相关复杂情况时,需要了解超文本传输协议,RFC 2616 是 HTTP 的权威参考文档。

二、获取 URL 资源

(一)简单获取

使用urllib.request最简单的方式是直接调用urlopen函数,传入目标 URL。例如:

import urllib.request
with urllib.request.urlopen('http://python.org/') as response:
    html = response.read()

如果想临时存储获取的资源,可以结合shutil.copyfileobj()tempfile.NamedTemporaryFile()函数:

import shutil
import tempfile
import urllib.request
with urllib.request.urlopen('http://python.org/') as response:
    with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
        shutil.copyfileobj(response, tmp_file)
    with open(tmp_file.name) as html:
        pass

(二)使用 Request 对象

urllib.requestRequest对象表示 HTTP 请求。创建Request对象并传入 URL,再用urlopen打开,可获取响应。例如:

import urllib.request
req = urllib.request.Request('http://python.org/')
with urllib.request.urlopen(req) as response:
    the_page = response.read()

urllib.request用同一接口处理所有 URL 方案,生成 FTP 请求只需修改 URL,如:

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

三、数据传输

在 HTTP 请求中,有时需要向 URL 发送数据,通常使用 POST 请求(也可在 GET 请求中传递数据)。向服务器发送数据时,数据需编码并作为data参数传给Request对象,编码使用urllib.parse库的函数。

(一)POST 请求

例如,向 CGI 脚本发送数据:

import urllib.parse
import urllib.request
url = 'http://www.someserver.com/cgi-bin/register.cgi'
values = {
    'name': 'Michael Foord',
    'location': 'Northampton',
    'language': 'Python'
}
data = urllib.parse.urlencode(values)
data = data.encode('ascii')  # 数据应为字节串
req = urllib.request.Request(url, data)
with urllib.request.urlopen(req) as response:
    the_page = response.read()

(二)GET 请求

在 GET 请求中传递数据,需将数据编码后添加到 URL 中:

import urllib.request
import urllib.parse
data = {}
data['name'] = 'Somebody Here'
data['location'] = 'Northampton'
data['language'] = 'Python'
url_values = urllib.parse.urlencode(data)
url = 'http://www.example.com/example.cgi'
full_url = url + '?' + url_values
data = urllib.request.urlopen(full_url)

四、HTTP 头部信息

HTTP 头部信息用于传递关于数据或请求本身的额外信息。有些网站会根据User - Agent头部信息识别客户端,urllib默认的User - Agent可能导致问题。可以在创建Request对象时,通过传入字典形式的头部信息来修改。例如,将自身标识为某个版本的 Internet Explorer:

import urllib.parse
import urllib.request
url = 'http://www.someserver.com/cgi-bin/register.cgi'
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 = urllib.parse.urlencode(values)
data = data.encode('ascii')
req = urllib.request.Request(url, data, headers)
with urllib.request.urlopen(req) as response:
    the_page = response.read()

五、异常的处理

(一)URLError

urlopen无法处理响应信息时,可能引发URLError(也可能引发其他内置异常)。通常是网络不通或服务器不存在导致,异常的reason属性包含错误代码和文本错误信息。例如:

import urllib.request
import urllib.error
req = urllib.request.Request('http://www.pretend_server.org')
try:
    urllib.request.urlopen(req)
except urllib.error.URLError as e:
    print(e.reason)

(二)HTTPError

HTTPErrorURLError的子类,在 HTTP URL 特定情况下引发。服务器返回的 HTTP 响应包含状态码,默认处理器会处理部分响应,无法处理的响应会引发HTTPError,如 “404”(页面未找到)、“403”(请求遭拒)等。HTTPError实例的code属性对应服务器的错误信息。

HTTP 错误码 含义
400 Bad Request,请求语法错误或不支持的方法
401 Unauthorized,需要身份认证
403 Forbidden,请求被禁止
404 Not Found,页面未找到
500 Internal Server Error,服务器内部错误

处理异常有两种基本方案:
第一种方案:

from urllib.request import Request, urlopen
from urllib.error 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: ', e.code)
except URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
else:
    # 一切正常

第二种方案:

from urllib.request import Request, urlopen
from urllib.error 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: ', e.reason)
    elif hasattr(e, 'code'):
        print('The server couldn\'t fulfill the request.')
        print('Error code: ', e.code)
else:
    # 一切正常

注意,except HTTPError必须首先被处理,否则except URLError将会同时捕获HTTPError

六、info 和 geturl 方法

urlopen返回的响应(或HTTPError实例)包含两个有用的方法info()geturl()

  • geturl():返回所获取页面的真实 URL,因为urlopen可能经过重定向,获取的页面 URL 未必是请求的 URL。
  • info():返回一个类似字典的对象,描述所获取的页面,包含服务器送出的头部信息,如'Content - length''Content - type'等。

七、Opener 和 Handler

获取 URL 时会使用openerurllib.request.OpenerDirector的实例),通常使用默认opener(通过urlopen),也可创建自定义openeropener使用handler来处理不同的 URL 方案或特定操作。

(一)创建自定义 opener

可以实例化OpenerDirector并调用.add_handler(some_handler_instance)添加handler,也可使用build_opener便捷函数创建opener对象。例如,创建处理基本认证的opener

import urllib.request
# 创建一个密码管理器
password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
# 添加用户名和密码
top_level_url = "http://example.com/foo/"
password_mgr.add_password(None, top_level_url, username, password)
handler = urllib.request.HTTPBasicAuthHandler(password_mgr)
# 创建 "opener" (OpenerDirector 实例)
opener = urllib.request.build_opener(handler)
# 使用 opener 获取一个 URL
opener.open(a_url)
# 安装 opener,之后调用 urlopen 会使用此 opener
urllib.request.install_opener(opener)

(二)代理设置

urllib会自动检测并使用代理设置(通过ProxyHandler),但有时需要自定义。例如,不使用代理时:

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

目前urllib.request尚不支持通过代理抓取https链接地址,但可通过扩展启用该功能。

八、套接字与分层

Python 获取 Web 资源的能力是分层的,urllib依赖http.client库,而http.client库又依赖套接字库。从 Python 2.3 开始,可以设置套接字等待响应的超时时间,避免程序挂起。例如:

import socket
import urllib.request
# 超时秒数
timeout = 10
socket.setdefaulttimeout(timeout)
req = urllib.request.Request('http://www.voidspace.org.uk')
response = urllib.request.urlopen(req)

总结

本文全面介绍了urllib包在 Python 中的使用方法,包括获取 URL 资源、处理数据和 HTTP 头部信息、异常处理、使用infogeturl方法,以及OpenerHandler的应用。通过学习这些内容,读者可以根据不同的网络需求,灵活运用urllib包实现各种网络数据获取任务。在实际编程中,要注意处理可能出现的异常情况,合理设置请求参数和头部信息,以确保程序的稳定性和正确性。

TAG: Python;urllib;网络资源获取;HTTP 请求;异常处理;Opener 和 Handler

学习资源和 URL

  1. Python 官方文档urllib.request 文档,提供了urllib.request模块的详细说明和函数用法。
  2. RFC 2616Hypertext Transfer Protocol -- HTTP/1.1,HTTP 协议的权威文档,深入了解 HTTP 协议的基础。
  3. ASPN Cookbook Recipeurllib 的 SSL 代理 opener (CONNECT 方法),用于扩展urllib.request支持通过代理抓取https链接地址。
  4. HTTP 标头快速参考:可通过搜索引擎查找相关资料,了解 HTTP 标头的完整列表及其含义和用法。
posted on 2025-02-20 15:35  TekinTian  阅读(40)  评论(0)    收藏  举报