1
0
wiki/Tech/programming-language/Python/进阶/拓展模块/网络处理/urllib URL 处理模块.md
2023-11-09 17:30:33 +08:00

12 KiB
Raw Blame History

title description keywords tags author date
urllib URL 处理模块 urllib URL 处理模块
python
urllib
Python/进阶
Python/标准库
7Wate 2023-08-29

概述

urllib 是 Python 标准库中用于处理 URL统一资源定位符相关操作的模块它提供了多个子模块用于执行网络请求、解析 URL、处理错误以及解析 robots.txt 文件等。以下是 urllib 的子模块:

子模块

  • urllib.request:提供打开和读取 URL 的功能。支持多种网络协议,如 HTTP、FTP 等。
  • urllib.error:包含与网络请求相关的异常类,用于处理错误和异常情况。
  • urllib.parse:用于解析和构建 URL提供各种操作如分割、组合、编码和解码。
  • urllib.robotparser:用于解析网站的 robots.txt 文件,确定哪些页面可以被爬取。

优点

  • 内置模块:作为 Python 标准库的一部分,无需单独安装。
  • 全面功能:支持多种网络协议和操作,适用于多种网络操作需求。
  • 高度可定制:用于处理 URL 的多个方面,如打开、读取、解析等。

缺点

  • 较低层次的 API:与一些第三方库相比(如 requestsurllib 的 API 较为底层,可能需要编写更多的代码。
  • 繁琐的错误处理:错误处理需要额外的代码,相比使用像 requests 这样的库可能更复杂。

同类产品对比

产品 优点 缺点 适用背景 社区支持
urllib 标准库,全面 API 较底层 网络请求URL 操作 Python 社区
requests API 简单 需要单独安装 HTTP 请求 Python 社区
httplib2 功能丰富 使用复杂 HTTP 请求 Python 社区

urllib.request

方法 功能描述 示例
urlopen() 打开并读取一个 URL 的内容 urllib.request.urlopen(url)
urlretrieve() 将 URL 指向的文件下载到本地 urllib.request.urlretrieve(url, filename)
build_opener() 构建一个可自定义的 Opener 对象 opener = urllib.request.build_opener()
install_opener() 安装全局的 Opener urllib.request.install_opener(opener)
HTTPBasicAuthHandler() HTTP 基础认证处理程序 handler = urllib.request.HTTPBasicAuthHandler()
HTTPCookieProcessor() 用于处理 HTTP cookies handler = urllib.request.HTTPCookieProcessor()
ProxyHandler() 设置代理 proxy = urllib.request.ProxyHandler({'http': 'http://www.example.com:8080'})
Request() 创建一个请求对象,用于定制 HTTP 头等 req = urllib.request.Request(url, headers={...})

urlopen() 打开 URL

import urllib.request

# 打开一个网页
response = urllib.request.urlopen('http://www.example.com')

# 读取网页内容
data = response.read()

# 输出网页内容
print(data)

urlretrieve() 下载文件

import urllib.request

# 从指定 URL 下载文件,并保存到本地
urllib.request.urlretrieve('http://www.example.com/file.txt', 'local_file.txt')

build_opener()install_opener()

build_opener() 传递一系列处理程序handlers这些处理程序用于定义如何处理各种 HTTP 功能比如重定向、基础认证、cookies 等。一旦你使用 build_opener() 创建了一个 Opener 对象,你可以使用 install_opener() 来设置它作为默认的 Opener

import urllib.request

# 创建基础认证处理程序
auth_handler = urllib.request.HTTPBasicAuthHandler()
auth_handler.add_password('realm', 'host', 'username', 'password')

# 创建代理处理程序
proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.proxy.com:8080'})

# 创建 Opener
opener = urllib.request.build_opener(auth_handler, proxy_handler)

# 安装 Opener
urllib.request.install_opener(opener)

# 使用 urlopen() 方法,这样会应用我们之前设置的所有处理程序
response = urllib.request.urlopen('http://www.example.com')

HTTP 基础认证 (HTTPBasicAuthHandler)

import urllib.request

# 创建一个 HTTPBasicAuthHandler 对象
auth_handler = urllib.request.HTTPBasicAuthHandler()

# 添加认证信息
auth_handler.add_password('realm', 'host', 'username', 'password')

# 创建并安装 opener
opener = urllib.request.build_opener(auth_handler)
urllib.request.install_opener(opener)

HTTPCookieProcessor 处理 Cookies

import urllib.request
import http.cookiejar

# 创建一个 CookieJar 对象
cookie_jar = http.cookiejar.CookieJar()

# 创建一个 HTTPCookieProcessor 对象
cookie_handler = urllib.request.HTTPCookieProcessor(cookie_jar)

# 构建和安装 opener
opener = urllib.request.build_opener(cookie_handler)

ProxyHandler 设置代理

import urllib.request

# 创建一个 ProxyHandler 对象
proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.proxy.com:8080'})

# 构建并安装 opener
opener = urllib.request.build_opener(proxy_handler)

Request() 自定义请求

import urllib.request

# 创建一个 Request 对象
req = urllib.request.Request(url='http://www.example.com', headers={'User-Agent': 'MyApp/1.0'})

# 使用 urlopen 打开自定义的请求
response = urllib.request.urlopen(req)

urllib.error

方法 功能描述
URLError 所有 urllib 产生的异常的基类
HTTPError 处理 HTTP 错误状态,继承自 URLError
ContentTooShortError 在下载过程中,数据不足时抛出的异常

URLError

当使用 urllib.request 打开一个 URL 失败时,通常会抛出 URLError 异常。

import urllib.request
import urllib.error

try:
    response = urllib.request.urlopen('http://www.nonexistentwebsite.com')
except urllib.error.URLError as e:
    print(e.reason)

HTTPError

当服务器返回 HTTP 错误状态码(如 404、500 等)时,会抛出 HTTPError

import urllib.request
import urllib.error

try:
    response = urllib.request.urlopen('http://www.example.com/404')
except urllib.error.HTTPError as e:
    print(f'HTTP Error Code: {e.code}')
    print(f'Reason: {e.reason}')

ContentTooShortError

如果使用 urlretrieve() 函数,但获取的数据长度与 Content-Length 头中声明的长度不匹配时,会抛出 ContentTooShortError

import urllib.request
import urllib.error

try:
    urllib.request.urlretrieve('http://www.example.com/file', 'local_file.txt')
except urllib.error.ContentTooShortError as e:
    print('The downloaded data is less than expected.')

urllib.parse

方法 功能描述 示例
urlparse() 解析 URL返回一个 ParseResult 对象 urllib.parse.urlparse(url)
urlunparse() 将 ParseResult 对象转回 URL urllib.parse.urlunparse(parse_result)
urlsplit() 类似于 urlparse(),但不分割 params urllib.parse.urlsplit(url)
urlunsplit() 将由 urlsplit() 返回的对象转回 URL urllib.parse.urlunsplit(split_result)
urljoin() 合并两个 URL urllib.parse.urljoin(base, url)
urlencode() 将字典或序列转换为 URL 查询字符串 urllib.parse.urlencode(query_dict)
quote() 将字符串进行 URL 编码 urllib.parse.quote(string)
unquote() 对 URL 编码的字符串进行解码 urllib.parse.unquote(encoded_string)

解析和构建 URL

from urllib.parse import urlparse, urlunparse, urlsplit, urlunsplit, urljoin

# 解析URL并返回ParseResult对象
parsed_url = urlparse('http://www.example.com/path?query=arg')

# 将ParseResult对象转换回URL
new_url = urlunparse(parsed_url)

# 类似于urlparse()但不分割params
split_result = urlsplit('http://www.example.com/path?query=arg')

# 将由urlsplit()返回的对象转换回URL
original_url = urlunsplit(split_result)

# 合并两个URL
new_url = urljoin('http://www.example.com/path/', '/anotherpath.html')

转换查询字符串

from urllib.parse import urlencode

# 将字典或序列转换为URL查询字符串
query_dict = {'key1': 'value1', 'key2': 'value2'}
query_string = urlencode(query_dict)

URL 编码和解码

from urllib.parse import quote, unquote

# 将字符串进行URL编码
encoded = quote('a string with / and ?')

# 对URL编码的字符串进行解码
decoded = unquote(encoded)

urllib.robotparser

通过使用 urllib.robotparser,你可以确保你的网络爬虫尊重网站的抓取策略,这是一种负责任的爬虫行为。

方法 功能描述 示例
RobotFileParser() 创建一个 RobotFileParser 对象 rp = urllib.robotparser.RobotFileParser()
set_url() 设置 robots.txt 文件的 URL rp.set_url('http://www.example.com/robots.txt')
read() 从设置的 URL 读取 robots.txt 文件 rp.read()
parse() 用于手动解析 robots.txt 文件的行 rp.parse(robots_txt_body.split("\n"))
can_fetch() 检查指定的 User-Agent 是否可以访问某个路径 rp.can_fetch('*', 'http://www.example.com/page')
mtime() 获取最后一次获取 robots.txt 文件的时间Unix 时间戳) rp.mtime()
modified() 设置最后一次获取 robots.txt 文件的时间 rp.modified()

创建和设置 RobotFileParser

首先,你需要创建一个 RobotFileParser 对象,并设置要解析的 robots.txt 文件的 URL。

import urllib.robotparser

# 创建 RobotFileParser 对象
rp = urllib.robotparser.RobotFileParser()

# 设置 robots.txt 文件的 URL
rp.set_url('http://www.example.com/robots.txt')

# 从 URL 读取 robots.txt 文件
rp.read()

检查爬虫是否可以访问特定页面

使用 can_fetch() 方法,您可以检查指定的 User-Agent 是否被允许抓取特定的网页路径。

# 检查 '*'(所有 User-Agents是否允许访问 '/page'
allowed = rp.can_fetch('*', 'http://www.example.com/page')

if allowed:
    print("I can crawl this page.")
else:
    print("I cannot crawl this page.")

手动解析 robots.txt

如果你需要手动解析 robots.txt 文件的内容,可以使用 parse() 方法。

# 假设 robots_txt_body 包含了 robots.txt 的文本内容
robots_txt_body = '''
User-agent: *
Disallow: /private/
'''

# 手动解析这些规则
rp.parse(robots_txt_body.split("\n"))