Python2与Python3中urllib库的差异及实战用法详解

陈默
陈默
发布时间:2026-10-13| 2人浏览过
原创

本文详细解析Python2与Python3中urllib库的模块合并与API变更,重点介绍Python3环境下urllib.request的核心功能。内容涵盖发送GET/POST请求、处理URL参数与中文编码、定制请求头以规避403错误、下载远程资源、配置代理IP以及Cookie会话维持和异常处理机制,为网络爬虫开发提供完整参考。

本文旨在梳理urllib库在Python不同版本间的演进变化,并重点基于Python3.X版本,系统讲解urllib库的实际应用方法。

urllib库版本对照速查表

Python2.X Python3.X
urllib urllib.request, urllib.error, urllib.parse
urllib2 urllib.request, urllib.error
urllib2.urlopen urllib.request.urlopen
urllib.urlencode urllib.parse.urlencode
urllib.quote urllib.request.quote
urllib2.Request urllib.request.Request
urlparse urllib.parse
urllib.urlretrieve urllib.request.urlretrieve
urllib2.URLError urllib.error.URLError
cookielib.CookieJar http.CookieJar

urllib是Python标准库中用于处理URL操作及页面爬取的核心模块,此外还有requests、httplib2等第三方库提供类似功能。

在Python2.X版本中,URL处理功能分散在urllib和urllib2两个模块中;而在Python3.X中,这些功能被统一整合至urllib模块下。通过上述对照表可以清晰看到主要API的变动路径,开发者可据此快速适配不同版本的Python代码。

相较于Python2.X,Python3.X在中文编码支持方面更为友好,因此下文将主要基于Python3.X环境,演示urllib库的常见操作技巧。

发送HTTP请求

import urllib.request
r = urllib.request.urlopen(http://www.python.org/)

首先需导入urllib.request模块,调用urlopen()函数向指定URL发送请求,该函数返回一个http.client.HTTPResponse对象,用于后续处理响应数据。

在urlopen()调用中,可通过timeout参数设定等待响应的超时秒数,防止请求挂起。此外,可利用r.info()获取响应头信息,r.getcode()获取HTTP状态码,r.geturl()获取当前实际请求的URL地址。

读取响应内容

import urllib.request
url = "http://www.python.org/"
with urllib.request.urlopen(url) as r:
r.read()

调用r.read()可将响应内容读取至内存,这通常对应网页的源代码(可通过浏览器“查看网页源代码”功能验证)。获取到的字符串数据可能需要通过decode()方法进行解码,以处理特定的字符编码。

传递URL参数

import urllib.request
import urllib.parse
params = urllib.parse.urlencode({'q': 'urllib', 'check_keywords': 'yes', 'area': 'default'})
url = "https://docs.python.org/3/search.html?{}".format(params)
r = urllib.request.urlopen(url)

若需向URL查询字符串传递数据,可将参数字典通过urlencode()函数进行编码处理。

编码后的params变量为字符串格式,字典中的每个键值对之间以'&'符号连接,例如:'q=urllib&check_keywords=yes&area=default'。

最终构建的完整URL示例为:https://docs.python.org/3/search.html?q=urllib&check_keywords=yes&area=default。

需要注意的是,urlopen()也支持直接接收已手动构建好的URL字符串。对于简单的GET请求,开发者可以不使用urlencode(),直接拼接URL后发起请求。不过,使用编码方法能使代码结构更模块化,逻辑也更清晰优雅。

传递中文参数

import urllib.request
searchword = urllib.request.quote(input("请输入要查询的关键字:"))
url = "https://cn.bing.com/images/async?q={}&first=0&mmasync=1".format(searchword)
r = urllib.request.urlopen(url)

以调用Bing图片接口查询关键字q的图片为例,若直接将中文字符串传入URL发起请求,可能会引发编码错误。此时应使用quote()函数对中文字符进行URL编码,必要时也可使用unquote()进行解码还原。

定制请求头

import urllib.request
url = 'https://docs.python.org/3/library/urllib.request.html'
headers = {
  'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
  'Referer': 'https://docs.python.org/3/library/urllib.html'
}
req = urllib.request.Request(url, headers=headers)
r = urllib.request.urlopen(req)

在爬取某些网页时,可能会遇到403 Forbidden错误,即服务器禁止访问。这通常是因为服务器对请求的Headers属性进行身份验证。例如,urllib库默认发送的请求中,User-Agent字段值为“Python-urllib/X.Y”(X为主版本号,Y为副版本号)。为了模拟浏览器行为,需通过urllib.request.Request()构建Request对象,并传入包含Headers属性的字典,以伪装请求来源。

所需的Headers具体信息,可通过浏览器开发者工具中的“检查”功能,在“Network”标签页查看目标网页的请求头获取;也可借助Fiddler、Wireshark等抓包分析软件进行提取。

除了上述方法,还可以利用urllib.request.build_opener()或req.add_header()来定制请求头,具体实现可参考官方示例代码。

在Python2.X环境中,通常需结合使用urllib和urllib2模块:利用urllib.urlencode()对URL参数进行编码,再通过urllib2.Request()构建Request对象以定制请求头,最后统一使用urllib2.urlopen()发送请求。

传递POST请求

import urllib.request
import urllib.parse
url = 'https://passport.cnblogs.com/user/signin?'
post = {
  'username': 'xxx',
  'password': 'xxxx'
}
postdata = urllib.parse.urlencode(post).encode('utf-8')
req = urllib.request.Request(url, postdata)
r = urllib.request.urlopen(req)

在进行注册、登录等需要提交表单的操作时,通常通过POST方式传递数据。

此时需先分析页面结构,构建表单数据post字典,使用urlencode()进行编码处理并返回字符串。由于POSTdata参数要求为bytes类型或file object,因此需指定'utf-8'编码格式进行转换。最后,通过Request()对象传递postdata,并使用urlopen()发送请求。

下载远程数据到本地

import urllib.request
url = "https://www.python.org/static/img/python-logo.png"
urllib.request.urlretrieve(url, "python-logo.png")

当需要爬取图片、视频等远程资源并保存至本地时,可使用urlretrieve()函数实现下载。

该函数的第一个参数为待下载的URL地址,第二个参数为下载文件在本地保存的路径。

示例代码演示了将Python官网logo下载至当前目录的过程,函数执行后返回一个元组(filename, headers),包含本地文件名及响应头信息。

设置代理IP

import urllib.request
url = "https://www.cnblogs.com/"
proxy_ip = "180.106.16.132:8118"
proxy = urllib.request.ProxyHandler({'http': proxy_ip})
opener = urllib.request.build_opener(proxy, urllib.request.HTTPHandler)
urllib.request.install_opener(opener)
r = urllib.request.urlopen(url)

若频繁爬取同一网页,可能导致IP被服务器屏蔽。此时可通过配置代理IP来解决访问限制问题。

首先从代理IP网站获取一个可用IP,构建ProxyHandler()对象,将'http'协议及代理IP以字典形式传入,以设置代理服务器信息。接着构建opener对象,传入proxy处理器和HTTPHandler类。最后通过install_opener()将opener设置为全局生效,此后调用urlopen()发送请求时,将自动使用配置的代理信息。

异常处理

import urllib.request
import urllib.error
url = "http://www.balabalabala.org"
try:
  r = urllib.request.urlopen(url)
except urllib.error.URLError as e:
  if hasattr(e, 'code'):
    print(e.code)
  if hasattr(e, 'reason'):
    print(e.reason)

可使用URLError类来处理与URL相关的异常情况。导入urllib.error模块后,捕获URLError异常。由于仅当发生HTTPError异常(URLError的子类)时,异常对象e才具备状态码属性code,因此需先判断异常对象是否包含code属性,再行处理。

Cookie的使用

import urllib.request
import http.cookiejar
url = "http://www.balabalabala.org/"
cjar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cjar))
urllib.request.install_opener(opener)
r = urllib.request.urlopen(url)

HTTP协议本身是无状态的,Cookie用于维持会话间的状态。例如,某些网站要求登录后才能访问特定内容。首次可通过提交POST表单登录,后续爬取该网站其他页面时,可利用Cookie保持登录状态,避免每次请求都重新提交表单登录。

具体实现时,首先构建CookieJar()对象cjar,再使用HTTPCookieProcessor()处理器处理该CookieJar,并通过build_opener()构建opener对象。将该opener设置为全局后,调用urlopen()发送请求即可自动携带Cookie信息。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。