当前位置: 首页 > news >正文

网络爬虫【爬虫库urllib】

  我叫不三不四,很高兴见到大家,欢迎一起学习交流和进步

今天来讲一讲爬虫

urllib介绍

Urllib是Python自带的标准库,无须安装,直接引用即可。

Urllib是一个收集几个模块来使用URL的软件包,大致具备以下功能。
● urllib.request:用于打开和读取URL。
● urllib.error:包含提出的例外urllib.request。
● urllib.parse:用于解析URL。
● urllib.robotparser:用于解析robots.txt文件。

发送请求

`urllib.request.urlopen`是 Python 中`urllib`模块的一个函数,用于打开和读取网络资源。以下是关于`urlopen`的语法和参数的详细说明:

语法

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

参数解释

1. url

• 含义:需要访问的网络资源的 URL 地址。

• 要求:URL 格式必须完整,包括协议(如`http://`或`https://`)。例如:

url = "https://movie.douban.com"


 • 错误示例:如果省略协议,如只写`movie.douban.com`,程序会提示无法识别 URL 的错误。
2. data

• 含义:用于发送请求的数据。

• 默认值:`None`。

• 请求方式:

• 如果`data`为`None`,则表示发送的是 GET 请求。

• 如果`data`不为`None`,则表示发送的是 POST 请求。

• 数据格式:`data`必须是字节类型(`bytes`),通常需要将字典通过`urllib.parse.urlencode()`转换为字符串,再用`encode()`转换为字节。例如:
 

import urllib.parse
data = {"key": "value"}
data = urllib.parse.urlencode(data).encode("utf-8")

3. timeout

• 含义:设置请求的超时时间(以秒为单位)。

• 默认值:未设置超时时间时,程序会一直等待,直到请求完成或发生错误。

• 作用:避免程序因网络延迟或服务器无响应而无限等待。例如:

response = urllib.request.urlopen(url, timeout=10)  # 超时时间为10秒

4. cafile

• 含义:指定用于验证服务器证书的 CA 证书文件路径。

• 默认值:`None`。

• 作用:在使用 HTTPS 请求时,用于验证服务器的身份。如果未指定,Python 会使用系统默认的 CA 证书。


5. capath

• 含义:指定包含 CA 证书的目录路径。

• 默认值:`None`。

• 作用:与`cafile`类似,但指定的是一个目录,而不是单个文件。


6. cadefault

• 含义:已废弃,不应使用。


7. context

• 含义:用于配置 SSL 上下文,通常用于 HTTPS 请求。

• 默认值:`None`。

• 作用:可以自定义 SSL 设置,例如禁用证书验证(不推荐,可能不安全)。例如:

import ssl
context = ssl._create_unverified_context()  # 禁用证书验证
response = urllib.request.urlopen(url, context=context)

示例代码

import urllib.request
import urllib.parse# 示例:发送 GET 请求
url = "https://movie.douban.com"
response = urllib.request.urlopen(url)
print(response.read())  # 读取响应内容# 示例:发送 POST 请求
data = {"key": "value"}
data = urllib.parse.urlencode(data).encode("utf-8")
response = urllib.request.urlopen(url, data=data)
print(response.read())  # 读取响应内容

注意事项

• 在使用`urlopen`时,需要确保 URL 格式正确,否则会引发`ValueError`或其他异常。

• 如果需要处理异常,可以使用`try-except`块捕获错误,例如超时或网络错误。

• 对于 HTTPS 请求,建议使用默认的证书验证,以确保安全。

 

更灵活的请求

`urllib.request.Request`是 Python 的`urllib`模块中用于创建 HTTP 请求对象的类。通过这个类,可以自定义请求头(headers)、请求方法(method)等信息,从而实现更灵活的网络请求。以下是关于`urllib.request.Request`的语法和参数的详细说明:
---

语法

urllib.request.Request(url, data=None, headers={}, method=None, origin_req_host=None, unverifiable=False, *, method=None)

---

参数解释

1. url

• 含义:需要访问的网络资源的 URL 地址。

• 要求:必须是完整的 URL,包括协议(如`http://`或`https://`)。例如:

url = "https://movie.douban.com"

• 作用:指定请求的目标地址。

2. data

• 含义:请求的附加数据。

• 默认值:`None`。

• 请求方式:

• 如果`data`为`None`,则默认为 GET 请求。

• 如果`data`不为`None`,则为 POST 请求。

• 数据格式:`data`必须是字节类型(`bytes`)。通常需要将字典通过`urllib.parse.urlencode()`转换为字符串,再用`encode()`转换为字节。例如:
 

import urllib.parse
data = {"key": "value"}
data = urllib.parse.urlencode(data).encode("utf-8")

3. headers

• 含义:自定义的 HTTP 请求头信息。

• 默认值:`{}`(空字典)。

• 作用:通过设置请求头,可以模拟浏览器的行为,绕过某些网站的反爬虫机制,或者添加必要的认证信息。例如:

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3","Accept-Language": "en-US,en;q=0.9"}


• 常见请求头字段:

• `User-Agent`:标识客户端的软件版本。

• `Accept-Language`:指定客户端的语言偏好。

• `Referer`:标识请求的来源页面。

• `Content-Type`:指定请求体的格式(如`application/json`或`application/x-www-form-urlencoded`)。


4. method

• 含义:显式指定请求方法(如 GET、POST、PUT、DELETE 等)。

• 默认值:根据`data`参数自动判断(`data=None`时为 GET,否则为 POST)。

• 作用:允许显式指定请求方法,避免依赖`data`参数来判断。例如:
 

request = urllib.request.Request(url, method="GET")

5. origin_req_host

• 含义:指定请求的来源主机名或 IP 地址。

• 默认值:`None`。

• 作用:用于某些特定的 HTTP/1.1 请求,通常不需要手动设置。


6. unverifiable

• 含义:标记请求是否为不可验证的请求。

• 默认值:`False`。

• 作用:用于某些特定的 HTTP/1.1 请求,通常不需要手动设置。


---示例代码
以下是一个使用`urllib.request.Request`设置请求头的完整示例:

import urllib.request
import urllib.parse# 目标 URL
url = "https://movie.douban.com"# 自定义请求头
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3","Accept-Language": "en-US,en;q=0.9"
}# 创建 Request 对象
request = urllib.request.Request(url, headers=headers)# 发送请求
response = urllib.request.urlopen(request)# 读取响应内容
print(response.read().decode("utf-8"))

注意事项

1. 请求头的重要性:某些网站会根据请求头中的信息(如`User-Agent`)判断请求是否来自合法的客户端。如果请求头设置不当,可能会被拒绝访问。

2. 数据编码:如果发送 POST 请求,`data`必须是字节类型。可以通过`urllib.parse.urlencode()`和`encode()`方法进行转换。

3. 显式指定方法:虽然`method`参数可以显式指定请求方式,但通常情况下,通过`data`参数来区分 GET 和 POST 请求已经足够。

通过`urllib.request.Request`,可以更灵活地控制 HTTP 请求的细节,从而实现更复杂的网络交互。

代理IP

原理

代理IP的原理:以本机先访问代理IP,再通过代理IP地址访问互联网,这样网站(服务器)接收到的访问IP就是代理IP地址。

以下是关于通过`urllib.request.ProxyHandler`动态设置 IP 池以及常见错误的描述:


---

动态设置 IP 池


在使用`urllib`进行网络请求时,可以通过`urllib.request.ProxyHandler`动态设置 IP 池,以实现代理请求。具体步骤如下:

1. 准备代理 IP 池:收集多个可用的代理 IP 地址,格式通常为`http://代理IP:端口`或`https://代理IP:端口`。

2. 创建`ProxyHandler`对象:将代理 IP 地址以字典形式传入`ProxyHandler`,例如:

proxies = {'http': 'http://代理IP1:端口','https': 'https://代理IP2:端口'
}
proxy_handler = urllib.request.ProxyHandler(proxies)


3. 构建`Opener`对象:使用`urllib.request.build_opener`方法将`ProxyHandler`添加到请求处理器中,并通过`install_opener`安装该`Opener`对象,使其生效。

   opener = urllib.request.build_opener(proxy_handler)urllib.request.install_opener(opener)



4. 发送请求:使用`urllib.request.urlopen`方法发送请求,此时请求会通过指定的代理 IP 发送。

response = urllib.request.urlopen(url)



通过动态设置 IP 池,可以有效隐藏真实 IP 地址,避免被目标服务器封禁,同时提高请求的稳定性和安全性。


---

常见错误及原因


在使用代理 IP 池时,可能会遇到以下常见错误:
1. `ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接`

• 原因:该错误通常表示目标服务器主动关闭了连接。可能的原因包括:

• 代理 IP 被目标服务器封禁或限制访问。

• 请求频率过高,触发了服务器的反爬虫机制。

• 代理服务器不稳定或配置错误。

• 解决方法:更换代理 IP,降低请求频率,确保代理服务器的稳定性。


2. `urllib.error.URLError: urlopen error Remote end closed connection without response`

• 原因:目标服务器在接收到请求后未返回任何响应,可能是因为:

• 代理服务器无法正常连接到目标服务器。

• 目标服务器拒绝了代理 IP 的请求。

• 网络连接不稳定或超时。

• 解决方法:检查代理 IP 的可用性,尝试更换代理服务器,或增加请求的超时时间。


3. `urllib.error.URLError: urlopen error [WinError 10054] 远程主机强迫关闭了一个现有的连接`

• 原因:与`ConnectionResetError`类似,该错误表示目标服务器关闭了连接。可能的原因包括:

• 代理 IP 被目标服务器封禁。

• 请求格式或参数不正确,导致服务器拒绝响应。

• 解决方法:更换代理 IP,检查请求头和参数是否符合目标服务器的要求。


4. `TimeoutError: [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,因此连接尝试失败`

• 原因:该错误表示请求超时,可能的原因包括:

• 网络连接不稳定或延迟过高。

• 代理服务器响应缓慢或无法连接到目标服务器。

• 请求的超时时间设置过短。

• 解决方法:增加请求的超时时间,更换代理服务器,或优化网络环境。


5. `urllib.error.URLError: urlopen error [WinError 10061] 由于目标计算机拒绝访问,因此`

• 原因:该错误表示目标服务器拒绝了连接请求,可能的原因包括:

• 目标服务器未运行或端口未开放。

• 代理 IP 被目标服务器拒绝访问。

• 请求的 URL 或端口错误。

• 解决方法:检查目标服务器的状态和端口是否开放,更换代理 IP,或验证请求的 URL 和端口是否正确。

cookies

通过提交数据实现用户登录之后,会生成带有登录状态的Cookies,这时可以将Cookies保存在本地文件中,下次程序运行的时候,可以直接读取Cookies文件来实现用户登录。特别对于一些复杂的登录,如验证码、手机短信验证登录这类网站,使用Cookies能简单解决重复登录的问题。

在 Python 中,`urllib`模块中的`HTTPCookieProcessor`用于处理 HTTP 请求中的 Cookies,而`MozillaCookieJar`是一个用于读写 Cookies 的工具。以下是一个使用`HTTPCookieProcessor`和`MozillaCookieJar`来处理 Cookies 的完整示例:


示例:使用`urllib`和`MozillaCookieJar`管理 Cookies

import http.cookiejar
import urllib.request# 创建一个 MozillaCookieJar 对象实例来保存 cookie
cookie_jar = http.cookiejar.MozillaCookieJar('cookies.txt')# 创建一个 HTTPCookieProcessor 对象并传入 cookie_jar
cookie_processor = urllib.request.HTTPCookieProcessor(cookie_jar)# 创建一个 opener 并传入 cookie_processor
opener = urllib.request.build_opener(cookie_processor)# 创建请求对象
url = "http://example.com"  # 替换为需要访问的网站
request = urllib.request.Request(url)# 使用 opener 发送请求并获取响应
response = opener.open(request)# 打印响应内容
print(response.read().decode('utf-8'))# 保存 cookies 到文件
cookie_jar.save(ignore_discard=True, ignore_expires=True)# 从文件加载 cookies
cookie_jar.load('cookies.txt', ignore_discard=True, ignore_expires=True)# 再次发送请求,此时会自动携带保存的 cookies
response_with_cookies = opener.open(request)
print(response_with_cookies.read().decode('utf-8'))


 

示例说明:

1. 创建`MozillaCookieJar`:用于保存和加载 Cookies。

• `cookie_jar = http.cookiejar.MozillaCookieJar('cookies.txt')`创建了一个`MozillaCookieJar`对象,并指定保存 Cookies 的文件名为`cookies.txt`。


2. 创建`HTTPCookieProcessor`:用于处理 HTTP 请求中的 Cookies。

• `cookie_processor = urllib.request.HTTPCookieProcessor(cookie_jar)`将`cookie_jar`传递给`HTTPCookieProcessor`,以便在 HTTP 请求中自动处理 Cookies。


3. 创建`opener`:用于发送 HTTP 请求。

• `opener = urllib.request.build_opener(cookie_processor)`创建了一个`opener`对象,并传入`cookie_processor`。


4. 发送请求并保存 Cookies:

• 使用`opener.open(request)`发送请求。

• 调用`cookie_jar.save(ignore_discard=True, ignore_expires=True)`将获取到的 Cookies 保存到文件中。


5. 从文件加载 Cookies:

• 使用`cookie_jar.load('cookies.txt', ignore_discard=True, ignore_expires=True)`从文件中加载 Cookies。


6. 再次发送请求:

• 再次使用`opener.open(request)`发送请求时,`HTTPCookieProcessor`会自动将加载的 Cookies 添加到请求中。
注意事项:

• `ignore_discard`和`ignore_expires`参数:这两个参数用于在保存和加载 Cookies 时忽略过期时间。

• 网站的 Cookie 策略:某些网站可能使用会话 Cookie,这些 Cookie 在浏览器关闭后会失效。因此,保存的 Cookies 可能无法在后续请求中使用。

• 安全性:Cookies 可能包含敏感信息(如会话 ID),在保存和加载 Cookies 时要注意安全性,避免泄露。

如何获取cookies

在之前的代码中,虽然涉及到了保存和加载 Cookies 的操作,但没有明确展示如何直接读取和查看保存的 Cookies。

在 Python 中,可以通过`MozillaCookieJar`或`CookieJar`的方法直接读取和查看 Cookies。


完整示例:使用`urllib`和`MozillaCookieJar`管理并读取 Cookies


import http.cookiejar
import urllib.request# 创建一个 MozillaCookieJar 对象实例来保存 cookie
cookie_jar = http.cookiejar.MozillaCookieJar('cookies.txt')# 创建一个 HTTPCookieProcessor 对象并传入 cookie_jar
cookie_processor = urllib.request.HTTPCookieProcessor(cookie_jar)# 创建一个 opener 并传入 cookie_processor
opener = urllib.request.build_opener(cookie_processor)# 创建请求对象
url = "http://example.com"  # 替换为需要访问的网站
request = urllib.request.Request(url)# 使用 opener 发送请求并获取响应
response = opener.open(request)# 打印响应内容
print(response.read().decode('utf-8'))# 保存 cookies 到文件
cookie_jar.save(ignore_discard=True, ignore_expires=True)# 从文件加载 cookies
cookie_jar.load('cookies.txt', ignore_discard=True, ignore_expires=True)# 再次发送请求,此时会自动携带保存的 cookies
response_with_cookies = opener.open(request)
print(response_with_cookies.read().decode('utf-8'))# 读取并打印 cookies
print("\n当前保存的 Cookies:")
for cookie in cookie_jar:print(f"Domain: {cookie.domain}, Name: {cookie.name}, Value: {cookie.value}")


 

补充说明:

1. 读取 Cookies:

• 在`MozillaCookieJar`对象中,可以通过迭代器的方式访问保存的 Cookies。

• `for cookie in cookie_jar:`遍历所有保存的 Cookies。

• 每个`cookie`对象是一个`http.cookiejar.Cookie`实例,包含以下属性:

• `cookie.domain`:Cookie 所属的域名。

• `cookie.name`:Cookie 的名称。

• `cookie.value`:Cookie 的值。


2. 打印 Cookies:

• 在代码中,通过`print(f"Domain: {cookie.domain}, Name: {cookie.name}, Value: {cookie.value}")`打印每个 Cookie 的详细信息。


3. 其他 Cookie 属性:

• 如果需要,还可以访问其他属性,例如:

• `cookie.path`:Cookie 的路径。

• `cookie.expires`:Cookie 的过期时间(时间戳)。

• `cookie.secure`:是否为安全 Cookie(仅在 HTTPS 下有效)。


示例输出:
假设访问的网站返回了以下 Cookies:

Set-Cookie: session_id=123456789; Path=/; Domain=example.com
Set-Cookie: user=guest; Path=/; Domain=example.com


运行代码后,打印的 Cookies 内容可能如下:
当前保存的 Cookies:

Domain: example.com, Name: session_id, Value: 123456789
Domain: example.com, Name: user, Value: guest

实际应用

在实际场景中,获取网站的 Cookies(尤其是登录相关的 Cookies)通常需要模拟登录过程,因为 Cookies 是服务器在用户登录后生成并返回的。如果直接访问一个需要登录的网站,而没有进行登录操作,服务器通常不会返回登录相关的 Cookies。


模拟登录以获取 Cookies
如果目标网站需要登录,那么在获取 Cookies 之前,必须先模拟登录过程。这通常涉及以下几个步骤:

1. 分析登录请求:查看登录页面的表单数据,确定需要提交的用户名、密码和其他参数。

2. 构造登录请求:使用`urllib`或其他库构造一个包含登录信息的 POST 请求。

3. 发送请求并获取响应:通过`HTTPCookieProcessor`自动处理服务器返回的 Cookies。

4. 保存和使用 Cookies:将获取到的 Cookies 保存到文件中,并在后续请求中使用这些 Cookies。


示例:模拟登录以获取 Cookies
以下是一个完整的示例,展示如何模拟登录一个需要认证的网站,并获取登录后的 Cookies。

import http.cookiejar
import urllib.request
import urllib.parse# 创建一个 MozillaCookieJar 对象实例来保存 cookie
cookie_jar = http.cookiejar.MozillaCookieJar('cookies.txt')# 创建一个 HTTPCookieProcessor 对象并传入 cookie_jar
cookie_processor = urllib.request.HTTPCookieProcessor(cookie_jar)# 创建一个 opener 并传入 cookie_processor
opener = urllib.request.build_opener(cookie_processor)# 登录信息
login_url = "https://example.com/login"  # 替换为实际的登录 URL
username = "your_username"
password = "your_password"# 构造表单数据
login_data = {"username": username,"password": password
}# 将表单数据编码为 bytes
encoded_data = urllib.parse.urlencode(login_data).encode('utf-8')# 创建登录请求
login_request = urllib.request.Request(login_url, data=encoded_data)# 发送登录请求
response = opener.open(login_request)# 检查登录是否成功(可以根据响应内容或状态码判断)
if response.getcode() == 200:print("登录成功!")# 保存 cookies 到文件cookie_jar.save(ignore_discard=True, ignore_expires=True)print("Cookies 已保存到 cookies.txt")
else:print("登录失败!")# 打印获取到的 Cookies
print("\n获取到的 Cookies:")
for cookie in cookie_jar:print(f"Domain: {cookie.domain}, Name: {cookie.name}, Value: {cookie.value}")


 

示例说明

1. 登录 URL 和表单数据:

• `login_url`是登录页面的 URL。

• `login_data`是需要提交的表单数据,通常包括用户名和密码。这些数据需要根据目标网站的登录表单进行调整。


2. 构造 POST 请求:

• 使用`urllib.parse.urlencode`将表单数据编码为 URL 编码格式。

• 将编码后的数据传递给`urllib.request.Request`,并指定请求方法为 POST。


3. 发送登录请求:

• 使用`opener.open(login_request)`发送登录请求。

• 如果登录成功,服务器会返回登录后的 Cookies,这些 Cookies 会被`HTTPCookieProcessor`自动保存到`cookie_jar`中。


4. 保存和打印 Cookies:

• 使用`cookie_jar.save()`将获取到的 Cookies 保存到文件中。

• 遍历`cookie_jar`并打印每个 Cookie 的详细信息。


注意事项

1. 登录失败的原因:

• 如果登录失败,可能是因为表单数据不正确(如用户名或密码错误)。

• 有些网站可能使用验证码或其他安全机制,需要额外处理。


2. 安全性:

• 在代码中明文存储用户名和密码是不安全的。在实际应用中,应避免将敏感信息硬编码到代码中。


3. HTTPS 和安全问题:

• 如果登录页面使用 HTTPS,确保在请求中正确处理 SSL/TLS 证书。

证书验证

当遇到一些特殊的网站时,在浏览器上会显示连接不是私密连接而导致无法浏览该网页。

CA证书,也称为SSL证书,是一种数字证书,类似于驾驶证、护照或营业执照的电子副本。由于它通常配置在服务器上,因此也被称为SSL服务器证书。SSL证书遵循SSL协议,由受信任的数字证书颁发机构(CA)颁发。在验证服务器身份后,CA会发放SSL证书,它具备服务器身份验证和数据传输加密的功能。SSL证书能够在客户端浏览器和Web服务器之间建立一条SSL安全通道(Secure Socket Layer,SSL)。SSL安全协议最初由Netscape Communication公司设计开发,主要用于对用户和服务器进行身份认证,对传输的数据进行加密和隐藏,并确保数据在传输过程中不被篡改,即保证数据的完整性。如今,SSL协议已成为该领域的全球化标准。

需要注意的是,一些特殊的网站可能会使用自己的证书,而不是由第三方CA颁发的标准证书。

遇到这类验证证书的网站,最简单而暴力的方法是直接关闭证书验证,可以在代码中引入SSL模块,设置关闭证书验证即可。

关闭 SSL 证书验证,发送一个 HTTP 请求到指定的 URL,并打印出响应的状态码。
 

import urllib.request
import ssl# 关闭证书验证
ssl._create_default_https_context = ssl._create_unverified_contexturl = 'https://kyfw.12306.cn/otn/leftTicket/init'
response = urllib.request.urlopen(url)# 输出状态码
print(response.getcode())

代码解释:

1. 导入模块:

• `urllib.request`用于发送网络请求。

• `ssl`用于处理 SSL 证书。


2. 关闭 SSL 证书验证:

• `ssl._create_default_https_context = ssl._create_unverified_context`这行代码将默认的 HTTPS 上下文替换为不验证证书的上下文。这通常用于测试目的,因为它会忽略 SSL 证书验证,这在生产环境中是不安全的。


3. 定义 URL:

• `url`变量存储了需要访问的网址。


4. 发送请求:

• 使用`urllib.request.urlopen(url)`发送请求到指定的 URL。


5. 打印状态码:

• `response.getcode()`获取 HTTP 响应的状态码,并打印出来。


注意事项:

• 安全性:关闭 SSL 证书验证会使你的应用容易受到中间人攻击。在生产环境中,你应该总是验证 SSL 证书。

• URL 有效性:确保你访问的 URL 是有效的,否则`urlopen`可能会抛出异常。

url编码

Python 中`urllib`模块在发送网络请求时,根据请求方式(GET 或 POST)以及数据编码的要求来处理请求参数。


---

1.`urllib.request.urlopen()`方法与请求方式

• `urllib.request.urlopen()`是 Python 中用来发送网络请求的一个方法。

• 它本身不直接区分是 GET 请求还是 POST 请求,而是通过参数`data`来判断:

• 如果`data`参数为`None`,那么默认是 GET 请求。

• 如果`data`参数不为`None`,那么会被视为 POST 请求。


2.POST 请求时`data`的处理

• 当你想发送 POST 请求时,`data`参数不能直接传入普通的字符串或字典,而是需要经过编码处理。

• 这里的编码处理是通过`urllib.parse`模块完成的:

• 首先,需要将参数(通常是字典形式)转换为 URL 编码的格式(例如:`key1=value1&key2=value2`)。

• 然后,将编码后的字符串转换为字节类型(因为网络传输需要字节类型的数据)。


3.数据编码的必要性

• 在网络请求中,如果需要传递数据(无论是 GET 的 URL 参数,还是 POST 的请求体),数据都需要被编码成一种标准的格式,以便在网络中传输。

• `urllib`要求数据必须是 ASCII 文本字符串(经过百分比编码的格式),并且如果是 POST 请求,还需要将字符串编码为字节类型。

• 如果不按照要求编码,直接传入字符串,就会导致`TypeError`错误。


---

举例说明


假设你想通过 POST 请求向服务器发送以下参数:

data = {'username': 'kimi', 'password': '123456'}


你需要按照以下步骤处理:

1. 编码参数为 URL 编码格式:

import urllib.parse
encoded_data = urllib.parse.urlencode(data)  # 结果是:'username=kimi&password=123456'

2. 将编码后的字符串转换为字节类型:

byte_data = encoded_data.encode('utf-8')  # 结果是:b'username=kimi&password=123456'

3. 发送 POST 请求:

import urllib.request
response = urllib.request.urlopen('http://example.com/login', data=byte_data)

如果直接传入字符串(如`'username=kimi&password=123456'`)而没有转换为字节类型,就会报`TypeError`错误。

特殊字符处理

1.`quote()`和`unquote()`的作用

• `quote()`:用于对字符串进行 URL 编码(也称为百分比编码)。它会将字符串中的特殊字符(如中文、空格、`@`、`&`等)转换为`%`加上两位十六进制数的形式。例如:

import urllib.parse
encoded_str = urllib.parse.quote("你好,世界!")
print(encoded_str)  # 输出:%E4%BD%A0%E5%A5%BD%EF%BC%8C%E4%B8%96%E7%95%8C%EF%BC%81

这样编码后的字符串可以安全地放在 URL 中传输,因为 URL 只能包含 ASCII 字符。


• `unquote()`:用于对经过 URL 编码的字符串进行解码,将其还原为原始字符串。例如:
 

decoded_str = urllib.parse.unquote("%E4%BD%A0%E5%A5%BD%EF%BC%8C%E4%B8%96%E7%95%8C%EF%BC%81")print(decoded_str)  # 输出:你好,世界!

2.解决中文内容的问题


在 URL 中,中文字符是不被允许的,因为 URL 只能包含 ASCII 字符。如果直接将中文放入 URL 中,可能会导致错误或无法正确解析。例如:

url = "http://example.com/search?q=你好"

这种 URL 在某些情况下可能会报错,或者服务器无法正确解析。

为了避免这种情况,可以使用`quote()`对中文内容进行编码:

import urllib.parse
url = "http://example.com/search?q=" + urllib.parse.quote("你好")
print(url)  # 输出:http://example.com/search?q=%E4%BD%A0%E5%A5%BD


这样编码后的 URL 就可以安全地发送请求了。
---

3.与`urlencode()`的区别

• `urlencode()`是用来编码字典形式的参数,生成`key=value&key=value`格式的查询字符串。它主要用于处理多个参数的情况,例如:

data = {'q': '你好', 'page': 1}
encoded_data = urllib.parse.urlencode(data)
print(encoded_data)  # 输出:q=%E4%BD%A0%E5%A5%BD&page=1

• `quote()`是用来单独对字符串进行编码,适用于单个参数或 URL 中的部分内容。例如:

encoded_str = urllib.parse.quote("你好")
print(encoded_str)  # 输出:%E4%BD%A0%E5%A5%BD

 

 

 

相关文章:

网络爬虫【爬虫库urllib】

我叫不三不四,很高兴见到大家,欢迎一起学习交流和进步 今天来讲一讲爬虫 urllib介绍 Urllib是Python自带的标准库,无须安装,直接引用即可。 Urllib是一个收集几个模块来使用URL的软件包,大致具备以下功能。 ● urlli…...

【一起来学kubernetes】17、Configmap使用详解

前言概述核心特性创建 ConfigMap使用 ConfigMap1. **环境变量**2. **Volume 挂载**3. **命令行参数** 更新与热重载Docker容器中Java服务使用Configmap**一、通过环境变量注入****步骤说明****示例配置** **二、通过 Volume 挂载配置文件****步骤说明****示例配置** **三、动态…...

QT程序双击可执行文件运行方法

1、qt编译选择release模式 在pro文件添加:QMAKE_LFLAGS -no-pie 2、cmake编译qt界面程序 在CMakeLists.txt文件中添加: set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -no-pie") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-pie")注意 …...

【css酷炫效果】实现鱼群游动动态效果

【css酷炫效果】实现小鱼游动动态效果 缘创作背景css代码创建div容器引入jquery引入鱼群js完整代码效果图成品资源下载链接:点击下载 缘 在开发系统功能的时候,无意间看到了小鱼游动特效,感觉很有意思,就在网上找了相关教程,分享给大家。 创作背景 刚看到csdn出活动了…...

【GNN】GAT

消息传递 层数越多,聚合更多的消息...

Prims region.Views 为null

原因: 导航未完成或异步问题 解决方式:使用回调确认导航完成后再操作视图 _regionManager.RequestNavigate("MonitorRegion", "MonitorView", nps, navigationResult > {if (navigationResult.Result true){var region _regio…...

在windows10系统上安装docker,然后在容器中运行GPU版本的Pytorch,并使用vscode连接该容器

一 . 安装Docker Desktop 首先打开网址https://docs.docker.com/desktop/install/windows-install/ 下载完后,双击下面的exe文件进行安装,默认情况下,Docker Desktop 安装在C:\Program Files\Docker\Docker 出现提示时,请确保…...

WPS 搭配 Zotero 插件使用

安装Zotero后,Word自动引入了插件,但WPS却没有,做为WPS的重度用户,这是不行的。 解决方案: 1.找到 Zotero.dotm 一般在安装目录下, 2.然后复制到WPS的startup下 我的目录是:C:\Users\lianq…...

卷积神经网络 - 卷积层(具体例子)

为了更一步学习卷积神经网络之卷积层,本文我们来通过几个个例子来加深理解。 一、灰度图像和彩色图像的关于特征映射的例子 下面我们通过2个例子来形象说明卷积层中“特征映射”的概念,一个针对灰度图像,一个针对彩色图像。 例子 1&#x…...

新造车不再比拼排名,恰是曲终人散时,剩者为王

据称新能源汽车周销量不再发布,这可能也预示着新造车终于到了给出答案的时候了,新造车企业前三强已基本确立,其余那些落后的车企已很难有突围的机会,而特斯拉无疑是其中的最大赢家。 3月份第一周的数据显示,销量最高的…...

学有所得-Deepin linux操作系统在安装nvidia显卡驱动后的问题修复

目标: 装有deepin V20.9的移动硬盘在系统启动后无法进入图形化界面,修复系统。 背景: 为了方便随时随地开发研究,又不破坏笔记本电脑原装的正版操作系统,在一个朗科(容量50&…...

【QT:网络编程】

网络编程的本质就是在编写应用层代码。需要传输层支持。而传输层的协议有UDP、TCP等 使用QT网络编程的API,需要在.pro文件中添加network模块,而QT中的控件和其他内容都是包含在QtCore模块中的(默认添加) QT为什么要划分模块&…...

基于srpingboot高校智慧校园教学管理服务平台的设计与实现(源码+文档+部署讲解)

技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...

分布式事务3PC解决了2PC哪些问题?

三阶段提交(3PC,Three-Phase Commit) 是对 二阶段提交(2PC,Two-Phase Commit) 的改进,旨在解决 2PC 的一些固有缺陷,特别是在分布式系统中的容错性和性能问题。以下是 3PC 比 2PC 更好的原因及其优势的详细分析: 1. 二阶段提交(2PC)的问题 2PC 是一种经典的分布式事…...

Dify 使用 - 创建 翻译 工作流

文章目录 1、选择 模板2、设置 和 基本使用3、运行应用 1、选择 模板 2、设置 和 基本使用 翻译模板 自带了系统提示词,你也可以修改 3、运行应用 右上角 点击 发布 – 更新,运行应用,就可以在新的对话界面中使用此功能 2025-03-18&#x…...

集成学习(上):Bagging集成方法

一、什么是集成学习? 在机器学习的世界里,没有哪个模型是完美无缺的。就像古希腊神话中的"盲人摸象",单个模型往往只能捕捉到数据特征的某个侧面。但当我们把多个模型的智慧集合起来,就能像拼图一样还原出完整的真相&a…...

c盘清理宝藏小工具

引言 在数字化时代,电脑的存储空间和系统性能直接影响着我们的工作效率和用户体验。C盘作为系统盘,常常因为文件堆积、缓存冗余等问题变得臃肿不堪,导致电脑运行缓慢。为了解决这一问题,我最近试用了一款名为“小番茄C盘清理”的…...

QT多媒体播放器类:QMediaPlayer

QMediaPlayer 是 Qt Multimedia 模块中的核心类,用于播放音频和视频媒体文件。它支持本地文件、网络流媒体以及实时数据源,具备播放控制、状态管理、元数据访问等功能。QMediaPlayer的基本用法可能包括设置媒体源、控制播放(播放、暂停、停止…...

Java动态代理模式深度解析

1. 动态代理基础 1.1 核心组件 Proxy 类:动态生成代理对象的工厂类,核心方法为 newProxyInstance()。 InvocationHandler 接口:代理逻辑的处理器,所有方法调用会转发到其 invoke() 方法。 1.2 实现步骤 定义接口:代…...

【WRF模拟】垂直层设置/与观测数据对比

【WRF模拟】垂直层设置/与观测数据对比 WRF 中 有关垂直层的namelist变量1. 主要垂直层设置参数2. 详细解释3. 典型设置示例WRF 输出的垂直剖面数据与观测数据进行比较WRF 采用 地形跟随坐标(terrain-following coordinate)WRF 输出的垂直剖面数据与观测数据进行比较参考WRF …...

植物知识分享论坛毕设

1.这四个文件直接是什么关系?各自都是什么作用?他们之间是如何联系的? 关系与联系 UserController.java 负责接收外部请求,调用 UserService.java 里的方法来处理业务, 而 UserService.java 又会调用 UserMapper.jav…...

可视化图解算法:链表中倒数(最后)k个结点

1. 题目 描述 输入一个长度为 n 的链表,设链表中的元素的值为ai ,返回该链表中倒数第k个节点。 如果该链表长度小于k,请返回一个长度为 0 的链表。 数据范围:0≤n≤105,0 ≤ai≤109,0 ≤k≤109 要求&am…...

qt下载和安装教程国内源下载地址

qt不断在更新中,目前qt6日渐成熟,先前我们到官方下载或者国内镜像直接可以下载到exe文件安装,但是最近几年qt官方似乎在逐渐关闭旧版本下载通道,列为不推荐下载。但是qt5以其广泛使用和稳定性,以及积累大量代码使得qt5…...

html5表格实战-跨行跨列

效果如图 代码如图...

使用OBS进行webRTC推流参考

参考腾讯云官方文档: 云直播 OBS WebRTC 推流_腾讯云 说明非常详细,分为通过WHIP和OBS插件的形式进行推流。 注意:通过OBS插件的形式进行推流需要使用较低的版本,文档里有说明,需要仔细阅读。...

Rockchip --- 图像时延优化

通过配置wait-line,即图像采集多少行后提前输出buffer给ISP,而无需等待图像全部采集完毕。一般设置为图像采集一半后提前输出buffer给ISP (一)VICAP提前输出 Video Input CAPture是用于图像采集和处理的子系统 1. 通过dts配置 …...

微软 LIDA 库:基于大模型的自动化数据分析与可视化

微软 LIDA 库:基于大模型的自动化数据分析与可视化 一、核心架构与 LLM 交互流程 #mermaid-svg-UzSwZNKPlgrJUpej {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-UzSwZNKPlgrJUpej .error-icon{fill:#5…...

java-正则表达式-集合-泛型

正则表达式 正则表达式到底是什么东西? 在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。 http://tool.oschina.net/r…...

力扣刷题994. 腐烂的橘子

994. 腐烂的橘子 - 力扣(LeetCode) 使用bfs,先遍历所有的橘子,统计所有的橘子数量,然后把腐烂的橘子放入队列当中,然后进行bfs遍历,套用bfs的模版,但是每一次出队的橘子&#xff08…...

Kubernetes的Service详解

一、Service介绍 在 kubernetes 中, pod 是应用程序的载体,我们可以通过 pod 的 ip 来访问应用程序,但是 pod 的 ip 地址不是固定的,这也就意味着不方便直接采用pod 的 ip 对服务进行访问。 为了解决这个问题,kuberne…...

Linux目录理解

前言 最近在复习linux,发现有些目录总是忘记内容,发现有些还是得从原义和实际例子去理解会记忆深刻些。以下是个人的一些理解 Linux目录 常见的Linux下的目录如下: 1. 根目录 / (Root Directory) 英文含义:/ 是文件系统的根…...

vue中js简单创建一个事件中心/中间件/eventBus

vue中js简单创建一个事件中心/中间件/eventBus 目录结构如下: eventBus.js class eventBus {constructor() {this.events {};}// 监听事件on(event, callback) {if (!this.events[event]) {this.events[event] [];}this.events[event].push(callback);}// 发射…...

1~2 课程简介+ESP32-IDF环境搭建(虚拟机Linux环境下)

哔站“宸芯IOT”视频链接 一、课程内容介绍 1.什么是ESP32 ESP32是集成2.4GHz Wi-Fi和蓝牙双模的单芯片方案,具有超高的射频性能、稳定性、通用性和可靠性,以及超低的功耗,满足不同的功耗需求,适用于各种应用场景。ESP32是ESP8…...

Linux系统移植篇(十一)Linux 内核启动流程

要分析 Linux 启动流程,同样需要先编译一下 Linux 源码,因为有很多文件是需要编译才 会生成的。首先分析 Linux 内核的连接脚本文件 arch/arm/kernel/vmlinux.lds,通过链接脚本可以 找到 Linux 内核的第一行程序是从哪里执行的。vmlinux.lds …...

React19源码系列之Hooks(useId)

useId的介绍 https://zh-hans.react.dev/reference/react/useId useId 是 React 18 引入的一个新 Hook,主要用于生成全局唯一的 ID。在开发中,我们经常需要为元素(如表单元素、模态框等)生成唯一 ID,以便在 JavaScri…...

深度学习-149-langchain之如何不使用with_structured_output()从模型中返回结构化数据

文章目录 1 不使用with_structured_output()方法1.1 问题背景1.2 输出解析器1.3 远程deepseek大模型API2 基于提示词2.1 直接使用提示词2.2 少样本提示词3 直接提示和解析模型输出3.1 使用PydanticOutputParser3.1.1 构建解析器3.1.2 构建提示模板3.1.3 调用大模型3.1.4 调用链…...

SAP DOI EXCEL应用

【应用场景】采用DOI方式打开填充EXCEL数据 *&---------------------------------------------------------------------* *& 包含 ZFI1009R_TOP *&---------------------------------------------------------------------* TABLES:bkpf,bseg. D…...

RS485电路设计注意事项

(一)RS485的电平标准: RS485用缆线两端的电压差值来表示传递信号,逻辑“1”以两线间的电压差为2V~6V标识,逻辑“0”以两线间的电压差为-2V~-6V标识。由此可见,接口信号电平较低,不易损坏接口电路…...

Git 回退操作详解:带示例的“小白”指南

前言 在日常开发中,我们难免会遇到: 改错代码:推送之前才发现某些行根本就不该动提交错误:commit 信息打错、提交到错误分支想回到之前版本:测试时发现之前版本是好的,需要回去查看 这就需要用到 Git 的…...

PyQt5库 各种导入项的作用

from PyQt5.QtCore import QIODevice, QSharedMemory, pyqtSignal 这行代码是从 PyQt5 库中导入了几个类和信号,用于开发桌面应用程序。下面是每个导入项的详细解释: QIODevice: QIODevice 是 PyQt5 中的一个类,提供了对输入输出设备的抽象…...

Git下载安装(保姆教程)

目录 1、Git下载 2、Git安装(windows版) (1)启动安装程序 (2)阅读许可协议 (3)选择安装路径 (4)选择组件 (5)选择开始菜单文件夹…...

关系数据库设计理论

目录 一、数据依赖——重点 (1)平凡依赖/非平凡函数依赖 (2)完全/部分函数依赖 (3)传递函数依赖 二、范式(NF) (1)第一范式 (2&#xff09…...

图解LLM智能体(LLM Agents):构建与运作机制的全面解析

LLM智能体:构建与运作机制 LLM智能体(LLM Agents)正在迅速普及,似乎逐渐取代了我们熟悉的传统对话式LLM。这些令人惊叹的能力并非凭空而来,而是需要多个组件协同工作。 本文包含超过60张定制插图,将深入探讨LLM智能体的领域、其核心组件以及多智能体框架的工作原理。 文…...

Anaconda 入门指南

Anaconda 入门指南 一、下载安装 Anaconda 1、下载地址:Anaconda 推荐下载 python3 版本, 毕竟未来 python2 是要停止维护的。 2、安装 Anaconda 按照安装程序提示一步步安装就好了, 安装完成之后会多几个应用: Anaconda Navigtor :用于管…...

YOLOv11小白的进击之路(九)创新YOLO11损失函数之NWD损失函数源码解读

之前的博客也有对YOLO11的损失函数进行过源码分析,可以参考:YOLOv11小白的进击之路(六)创新YOLO的iou及损失函数时的源码分析_yolov11的损失函数是什么-CSDN博客最近在做小目标检测的时候注意到了NWD损失函数,这里对其…...

【c++】内存序 和 内存一致性模型

c 11 中为了支持并发,定义了内存序和内存一致性模型。这个概念听起来非常高深,好像是在多线程编程领域浸淫多年之后的神级程序员才能搞明白,并用明白的东西。 本文尝试用最简单的方式说清楚这个概念。因为这个概念真的超级简单,大…...

力扣128. 最长连续序列 || 452. 用最少数量的箭引爆气球

最长连续列 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 输入:nums [100,4,200,1,3,2] 输出:4 解释&…...

从零开始写C++3D游戏引擎(开发环境VS2022+OpenGL)之十一点二五 光照贴图(lighting maps)的实现 细嚼慢咽逐条读代码系列

写在篇前的话 作为一个曾经在代码堆里面苦苦挣扎的萌新,困惑的事情在于库,各种依赖,包换文件,链接库,纠结于代码的作用意义。尤其在3D引擎开发的问题上,很多人都被各种困难给阻拦,放弃了在3D渲染,3D游戏引擎上大涨鸿图的机会。 当然关于3D游戏引擎的教程已经汗牛充栋…...

优先级队列(PriorityQueue)_1_模拟实现优先级队列

1、概念 前面介绍过队列,队列是一种先进先出(FIFO)的数据结构 ,但有些情况下, 操作的数据可能带有优先级,一般出队 列时,可能需要优先级高的元素先出队列 ,这时候,使用队列显然不合适了。 在这种…...

java后端怎么写好根据角色控制查询不同数据,

z总的思路,先把不带查询条件的包含角色控制场景(比如:总公司经理角色可以查看所有数据,但是暂存的话只能查自己暂存的,分公司,只能查自己所属分公司的,)的所有数据查出来 例如查询的…...