Python 爬虫库 urllib 使用详解
一、Python urllib 库概述
Python urllib 库用于操作网页 URL,并对网页的内容进行抓取处理。它是 Python 标准库的一部分,无需额外安装。
Python3 的 urllib 包包含以下几个核心模块:
urllib.request- 打开和读取 URL。urllib.error- 包含 urllib.request 抛出的异常。urllib.parse- 解析 URL。urllib.robotparser- 解析 robots.txt 文件。
在实际开发中,主要使用每个模块的内置方法和函数。
二、urllib.request 模块
urllib.request 定义了一些打开 URL 的函数和类,包含授权验证、重定向、浏览器 cookies 等功能。它可以模拟浏览器的一个请求发起过程。
2.1 urlopen 函数
语法格式如下:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
参数说明:
url:URL 地址。data:发送到服务器的其他数据对象,默认为 None(用于 POST 请求)。timeout:设置访问超时时间,防止程序无限挂起。cafile和capath:CA 证书及路径,使用 HTTPS 时需要用到。cadefault:已被弃用。context:ssl.SSLContext 类型,用来指定 SSL 设置。
示例:
import urllib.request
# 导入 urllib.request 模块
url = "https://www.baidu.com"
response = urllib.request.urlopen(url)
# 获取响应内容并解码
html = response.read().decode('utf-8')
print(html[:500]) # 仅打印前 500 字符
Response 对象属性与方法:
response 对象是 http.client.HTTPResponse 类型,主要包含以下方法:
read():读取整个网页内容,也可以指定读取的长度,如 read(300)。获取到的是二进制数据,通常需要 decode() 解码。readline():读取文件的一行内容。readlines():读取文件的全部内容,返回一个列表。info():返回 HTTPMessage 对象,表示远程服务器返回的头信息。getcode():返回 HTTP 状态码。200 表示成功,404 表示未找到。geturl():返回请求的 URL。
2.2 Request 类
在抓取网页时,通常需要对 headers(网页头信息)进行模拟,否则网页很容易判定程序为爬虫,从而禁止访问。此时需要使用 urllib.request.Request 类。
语法:
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
参数说明:
url:URL 地址。headers:HTTP 请求的头部信息,字典格式。method:请求方法,如 GET、POST、DELETE、PUT 等。
示例:
import urllib.request
url = "https://www.baidu.com"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36"
}
req = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(req)
html = response.read().decode("utf-8")
print(response.getcode())
三、urllib.error 模块
urllib.error 模块为 urllib.request 所引发的异常定义了异常类,基础异常类是 URLError。
该模块包含两个主要异常类:URLError 和 HTTPError。
- URLError:是 OSError 的一个子类,用于处理程序在遇到问题时会引发此异常(或其派生的异常),包含的属性 reason 为引发异常的原因。
- HTTPError:是 URLError 的一个子类,用于处理特殊 HTTP 错误例如作为认证请求的时候,包含的属性 code 为 HTTP 的状态码,reason 为引发异常的原因,headers 为导致 HTTPError 的特定 HTTP 请求的 HTTP 响应头。
区别与关系:
- URLError 封装的错误信息一般是由网络引起的,包括 URL 错误。
- HTTPError 封装的错误信息一般是服务器返回了错误状态码。
- 继承关系:URLError 是 OSError 的子类,HTTPError 是 URLError 的子类。
3.1 URLError 示例
from urllib import request
from urllib import error
try:
url = "http://www.baiiiduuuu.com/"
req = request.Request(url)
response = request.urlopen(req)
html = response.read().decode('utf-8')
print(html)
except error.URLError as e:
print(f"URLError: {e.reason}")
3.2 HTTPError 示例
from urllib import request
from urllib import error
try:
url = "http://www.baidu.com/no.html"
req = request.Request(url)
response = request.urlopen(req)
html = response.read().decode('utf-8')
print(html)
except error.HTTPError as e:
print(f"HTTPError Code: {e.code}")
print(f"Reason: {e.reason}")
3.3 混合异常处理
注意:由于 HTTPError 是 URLError 的子类,所以捕获的时候 HTTPError 要放在 URLError 的上面。
from urllib import request
from urllib import error
try:
url = "http://www.baidu.com/no.html"
req = request.Request(url)
response = request.urlopen(req)
except error.HTTPError as e:
print("HTTP Error occurred")
print(e.code)
except error.URLError as e:
print("URL Error occurred")
print(e.reason)
四、urllib.parse 模块
模块定义的函数可分为两个主要门类:URL 解析和 URL 转码。
4.1 URL 解析
4.1.1 urlparse()
urllib.parse 用于解析 URL。
from urllib.parse import urlparse
o = urlparse("https://docs.python.org/zh-cn/3/library/urllib.parse.html#module-urllib.parse")
print('scheme :', o.scheme)
print('netloc :', o.netloc)
print('path :', o.path)
print('params :', o.params)
print('query :', o.query)
print('fragment:', o.fragment)
返回值是一个 NamedTuple,包含六个元素:协议(scheme)、域名(netloc)、路径(path)、路径参数(params)、查询参数(query)、片段(fragment)。
4.1.2 urlunparse()
urlunparse() 可以实现 URL 的构造。它接收一个长度为 6 的可迭代对象,将 URL 的多个部分组合为一个 URL。
from urllib.parse import urlunparse
url_compos = ['http', 'www.baidu.com', 'index.html', 'user=test', 'a=6', 'comment']
result_url = urlunparse(url_compos)
print(result_url)
4.1.3 urlsplit() 与 urlunsplit()
urlsplit() 函数也能对 URL 进行拆分,所不同的是,urlsplit() 并不会把路径参数 (params) 从路径 (path) 中分离出来。当 URL 中路径部分包含多个参数时,使用 urlparse() 解析是有问题的,这时可以使用 urlsplit() 来解析。
urlunsplit() 与 urlunparse() 类似,但传入对象必须是可迭代对象,且长度必须是 5。
4.1.4 urljoin()
传递一个基础链接,根据基础链接可以将某一个不完整的链接拼接为一个完整链接。如果第二个参数有完整的路径,则以第二个为主。
4.2 URL 转码
Python 中提供 urllib.parse 模块用来编码和解码,分别是 urlencode() 与 unquote()。
4.2.1 quote(string)
URL 转码函数的功能是接收程序数据并通过对特殊字符进行转码并正确编码非 ASCII 文本来将其转为可以安全地用作 URL 组成部分的形式。
from urllib import parse
url = "http://www.baidu.com/s?wd={}"
words = "爬虫"
query_string = parse.quote(words)
url = url.format(query_string)
print(url)
4.2.2 urlencode()
quote() 只能对字符串编码,而 urlencode() 可以对查询字符串进行编码。
from urllib import parse
query_string = {'wd': '爬虫'}
result = parse.urlencode(query_string)
url = 'http://www.baidu.com/s?{}'.format(result)
print(url)
4.2.3 unquote(string)
解码就是对编码后的 URL 进行还原。
from urllib import parse
string = '%E7%88%AC%E8%99%AB'
result = parse.unquote(string)
print(result)
五、urllib.robotparser 模块
urllib.robotparser 用于解析 robots.txt 文件。Robots 协议是一种存放于网站根目录下的文本文件,通常用于告诉搜索引擎对网站的抓取规则。
urllib.robotparser 提供了 RobotFileParser 类。
from urllib.robotparser import RobotFileParser
rp = RobotFileParser()
rp.set_url("https://www.example.com/robots.txt")
rp.read()
if rp.can_fetch("*", "https://www.example.com/page"):
print("允许爬取")
else:
print("禁止爬取")
常用方法:
set_url(url):设置 robots.txt 文件的 URL。read():读取 robots.txt URL 并将其输入解析器。can_fetch(useragent, url):如果允许 useragent 按照被解析 robots.txt 文件中的规则来获取 url 则返回 True。
六、实战建议与最佳实践
在实际爬虫开发中,除了掌握基本 API,还需注意以下几点以提升稳定性和合规性:
- 设置 User-Agent:始终模拟真实浏览器,避免被目标站点封禁 IP。
- 控制请求频率:添加随机延时,避免对服务器造成过大压力。
- 异常处理:务必使用 try-except 块包裹网络请求代码,防止因网络波动导致程序崩溃。
- 遵守 Robots 协议:在大规模爬取前,检查目标站点的 robots.txt 文件,尊重网站方的爬取限制。
- 数据清洗:获取到的 HTML 内容通常包含大量标签,建议使用 BeautifulSoup 或 lxml 进一步提取所需数据。
通过合理使用 urllib 及其子模块,开发者可以快速构建稳定的网络数据采集工具。

