一、Python urllib
urllib
是 Python 的一个标准库,用于打开和读取 URLs。它提供了一组模块,允许你以编程方式从网络获取数据,如网页内容、文件等。urllib
包括以下模块:
urllib.request
:用于打开和读取 URLs。urllib.error
:定义了在打开和读取 URLs 时可能引发的异常。urllib.parse
:用于解析 URLs 和 URL 组件。urllib.robotparser
:用于解析robots.txt
文件,该文件指示网络爬虫哪些页面可以或不可以抓取。
下面是一些使用 urllib
模块的基本示例:
1. 使用 urllib.request
打开和读取 URL
使用 urllib.request 的 urlopen 方法来打开一个 URL,语法格式如下:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
属性 | 描述 |
---|---|
url|url 地址。
data|发送到服务器的其他数据对象,默认为 None。
timeout|设置访问超时时间。
cafile 和 capath|cafile 为 CA 证书, capath 为 CA 证书的路径,使用 HTTPS 需要用到。
cadefault|已经被弃用。
context|ssl.SSLContext类型,用来指定 SSL 设置。
urllib.request
是 Python 的一个标准库模块,用于打开和读取 URL。这个模块提供了一个高级接口,使得你可以轻松地以编程方式从网络获取数据。它支持常见的网络协议,如 HTTP、HTTPS、FTP 等,并允许你定制请求头、处理重定向、使用代理等。
下面是一些使用 urllib.request
的基本示例:
打开并读取 URL
import urllib.request
url = 'http://example.com'
with urllib.request.urlopen(url) as response:
html_content = response.read()
print(html_content)
设置请求头
import urllib.request
url = 'http://example.com'
req = urllib.request.Request(url, headers={
'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req) as response:
html_content = response.read()
print(html_content)
处理重定向
urllib.request
默认会处理 HTTP 重定向。
import urllib.request
url = 'http://example.com/redirect'
with urllib.request.urlopen(url) as response:
redirected_url = response.geturl()
html_content = response.read()
print(redirected_url)
print(html_content)
使用代理
你可以通过创建一个自定义的 OpenerDirector
来使用代理。
import urllib.request
from urllib.request import ProxyHandler, build_opener
proxy_handler = ProxyHandler({
'http': 'http://proxy.example.com:8080'})
opener = build_opener(proxy_handler)
url = 'http://example.com'
with opener.open(url) as response:
html_content = response.read()
print(html_content)
错误处理
使用 try...except
来处理可能出现的异常,如 URLError
和 HTTPError
。
import urllib.request
from urllib.error import URLError, HTTPError
url = 'http://invalid-url.com'
try:
with urllib.request.urlopen(url) as response:
html_content = response.read()
print(html_content)
except URLError as e:
print('We failed to reach a server.')
print('Reason:', e.reason)
except HTTPError as e:
print('The server couldn\'t fulfill the request.')
print('Error code:', e.code)
print('Error message:', e.read())
发送 POST 请求
import urllib.request
import urllib.parse
url = 'http://example.com/post'
data = urllib.parse.urlencode({
'key1': 'value1', 'key2': 'value2'}).encode()
req = urllib.request.Request(url, data, method='POST')
with urllib.request.urlopen(req) as response:
html_content = response.read()
print(html_content)
urllib.request
提供了许多其他功能和选项,可以满足大多数基本的网络请求需求。然而,对于更复杂的用例,如使用 OAuth 进行身份验证、发送 JSON 数据、处理 cookies 等,你可能需要查看更高级的库,如 requests
。requests
库提供了一个更加友好和强大的 API,使得发送 HTTP 请求变得更加简单和直观。
2. 使用 urllib.parse
解析 URL
urllib.parse
是 Python 标准库中的一个模块,它提供了用于解析 URL 的各种功能。这个模块允许你拆分、合并、引用和转义 URL 组件。以下是 urllib.parse
的一些常用功能:
拆分 URL
使用 urlparse()
函数可以将 URL 字符串拆分为组件。
from urllib.parse import urlparse
url = 'http://www.example.com/path?name=value#fragment'
parsed = urlparse(url)
print(parsed.scheme) # http
print(parsed.netloc) # www.example.com
print(parsed.path) # /path
print(parsed.params) # None
print(parsed.query) # name=value
print(parsed.fragment) # fragment
合并 URL
使用 urlunparse()
函数可以将组件重新组合成 URL 字符串。
from urllib.parse import urlunparse
parts = ('http', 'www.example.com', '/path', None, 'name=value', 'fragment')
url = urlunparse(parts)
print(url) # http://www.example.com/path?name=value#fragment
引用和转义 URL
quote()
和 unquote()
函数用于对 URL 字符串中的特殊字符进行转义和解转义。
from urllib.parse import quote, unquote
# 转义
escaped_string = quote('Hello, World!')
print(escaped_string) # Hello%2C%20World%21
# 解转义
unescaped_string = unquote(escaped_string)
print(unescaped_string) # Hello, World!
解析查询字符串
parse_qs()
和 parse_qsl()
函数用于解析 URL 查询字符串。
from urllib.parse import parse_qs, parse_qsl
query_string = 'key1=value1&key2=value2'
# 返回一个字典,键是唯一的,如果有多个相同的键,则它们的值是一个列表
query_dict = parse_qs(query_string)
print(query_dict) # {'key1': ['value1'], 'key2': ['value2']}
# 返回一个列表,每个元素都是一个元组,包含键和值
query_list = parse_qsl(query_string)
print(query_list) # [('key1', 'value1'), ('key2', 'value2')]
构建查询字符串
urlencode()
函数用于将字典或元组列表转换为查询字符串。
from urllib.parse import urlencode
params = {
'key1': 'value1', 'key2': 'value2'}
query_string = urlencode(params)
print(query_string) # key1=value1&key2=value2
urllib.parse
模块还提供了其他一些功能,如 urljoin()
(用于连接基础 URL 和相对路径),urldefrag()
(用于移除 URL 的片段部分),以及 unquote_plus()
(用于处理空格和其他特殊字符)。
在处理 URL 时,urllib.parse
模块是非常有用的,它可以帮助你解析、构建和操纵 URL。
3. 使用 urllib.error
处理异常
urllib.error
是 Python 的一个标准库模块,它定义了与 urllib.request
一起使用的异常类。当使用 urllib.request
来打开或读取 URL 时,可能会遇到各种错误,例如网络问题、无效的 URL 或服务器错误。urllib.error
模块提供了异常类,以帮助你更好地处理这些错误。
以下是 urllib.error
模块中定义的一些异常类:
URLError
这是一个基础异常类,用于处理与 URL 相关的错误。当你尝试打开一个 URL 但由于某种原因失败时,通常会抛出这个异常。
from urllib.error import URLError
from urllib.request import urlopen
try:
response = urlopen('http://invalid-url')
except URLError as e:
print(f"URL Error: {e.reason}")
HTTPError
这是一个特定于 HTTP 错误的异常类,继承自 URLError
。当服务器返回一个 HTTP 错误代码(如 404 Not Found)时,会抛出此异常。
from urllib.error import HTTPError
from urllib.request import urlopen
try:
response = urlopen('http://example.com/nonexistent')
except HTTPError as e:
print(f"HTTP Error: {e.code} {e.reason}")
ContentTooShortError
当从 URL 读取的内容比预期的要短时,会抛出此异常。这通常在使用 urlopen
与文件类对象(如 urlopen(url, data)
)一起使用时发生。
RequestError
当请求中发生错误时,会抛出此异常。它通常不直接由用户处理,而是作为其他更具体错误的基类。
处理 urllib.request
产生的异常时,通常使用 try...except
块来捕获并处理这些异常。你可以根据异常的类型执行不同的操作,如记录错误、重试请求或向用户显示友好的错误消息。
例如:
from urllib.error import URLError, HTTPError
from urllib.request import urlopen
try:
response = urlopen('http://example.com')
# 处理响应...
except HTTPError as e:
# 处理 HTTP 错误...
print(f"HTTP Error: {e.code} {e.reason}")
except URLError as e:
# 处理其他 URL 错误...
print(f"URL Error: {e.reason}")
这样,你的代码就能更健壮地处理网络请求中可能出现的各种错误情况。
4. 使用urllib.robotparser
解析 robots.txt
文件
urllib.robotparser
是 Python 标准库中的一个模块,它用于解析 robots.txt
文件。robots.txt
是一个放置在网站根目录下的文本文件,用于指示网络爬虫(web crawlers)或搜索引擎机器人(search engine robots)哪些页面可以访问,哪些页面不能访问。
urllib.robotparser
模块提供了一个 RobotFileParser
类,你可以使用这个类来解析 robots.txt
文件,并查询特定的用户代理(user agent)是否允许访问特定的路径。
下面是一个使用 urllib.robotparser
的基本示例:
import urllib.robotparser
# 创建一个 RobotFileParser 实例
rp = urllib.robotparser.RobotFileParser()
# 设置要解析的 robots.txt 文件的 URL(通常是一个本地文件路径或网络 URL)
# 这里我们使用一个示例的字符串来代替实际的文件内容
robots_txt_content = """
User-agent: *
Disallow: /private/
Disallow: /temp/
User-agent: Googlebot
Allow: /temp/
"""
# 使用 set_url 方法来设置要解析的内容,通常这是一个 URL,但也可以是字符串内容
rp.set_url("http://example.com/robots.txt", robots_txt_content)
# 检查特定用户代理是否可以访问特定路径
user_agent = "Googlebot"
path = "/temp/somefile.html"
if rp.can_fetch(user_agent, path):
print(f"{user_agent} is allowed to fetch {path}")
else:
print(f"{user_agent} is not allowed to fetch {path}")
# 对于不在 robots.txt 中明确允许的路径,默认是允许的
path = "/public/index.html"
if rp.can_fetch(user_agent, path):
print(f"{user_agent} is allowed to fetch {path} (by default)")
else:
print(f"{user_agent} is not allowed to fetch {path} (by default)")
在这个示例中,我们创建了一个 RobotFileParser
实例,并使用 set_url
方法来设置要解析的 robots.txt
文件内容。然后,我们使用 can_fetch
方法来检查特定的用户代理(例如 "Googlebot")是否可以访问特定的路径(例如 "/temp/somefile.html")。
请注意,urllib.robotparser
模块并不提供网络功能来自动下载 robots.txt
文件。你需要手动获取 robots.txt
文件的内容,并将其传递给 set_url
方法。如果你想要从网络上下载并解析 robots.txt
文件,你需要使用其他工具,如 urllib.request
。