如果您需要使用 Python 发出 HTTP 请求,那么您可能会发现自己被引导至 brilliantrequests库。尽管它是一个很棒的库,但您可能已经注意到它并不是 Python 的内置部分。如果您出于某种原因更喜欢限制依赖项并坚持使用标准库 Python,那么您可以使用urllib.request!
在本教程中,您将:
了解如何发出基本的HTTP 请求urllib.request
深入了解HTTP 消息的具体细节及其urllib.request表示方式
了解如何处理HTTP 消息的字符编码
探索使用时的一些常见错误urllib.request并学习如何解决它们
将您的脚趾浸入经过身份验证的请求的世界urllib.request
理解为什么两者urllib和requests库都存在以及何时使用其中一个或另一个
如果您听说过 HTTP 请求,包括GET和POST,那么您可能已经准备好学习本教程了。此外,您应该已经使用 Python读取和写入文件,最好使用上下文管理器,至少一次。
最终,您会发现提出请求不一定是令人沮丧的经历,尽管它确实有这样的名声。您经常遇到的许多问题都是由于 Internet 这个奇妙事物的内在复杂性造成的。好消息是该urllib.request模块可以帮助揭开这种复杂性的神秘面纱。
了解更多信息: 单击此处与 290,000 多名 Python 开发人员一起阅读 Real Python Newsletter ,获取新的 Python 教程和新闻,让您成为更高效的 Pythonista。
在深入了解什么是 HTTP 请求及其工作原理之前,您需要通过向示例 URL发出基本的 GET 请求来了解一下。您还将向模拟REST API发出 GET 请求以获取某些JSON数据。如果您想了解 POST 请求,一旦您对urllib.request.
Beware:根据您的具体设置,您可能会发现其中一些示例不起作用。如果是这样,请跳到有关常见 urllib.request 错误 的部分以进行故障排除。如果您遇到此处未涵盖的问题,请务必在下面使用精确且可重现的示例进行评论。
首先,您将向 发出请求www.example.com,服务器将返回一条 HTTP 消息。确保您使用的是 Python 3 或更高版本,然后使用urlopen()函数 from urllib.request:
from urllib.request import urlopen
with urlopen("https://www.example.com") as response:
body = response.read()
body[:15]
b''
在此示例中,您urlopen()从urllib.request. 使用上下文管理器 with,您可以发出请求并接收响应urlopen()。然后您读取响应的主体并关闭响应对象。这样,您就可以显示正文的前十五个位置,并指出它看起来像一个 HTML 文档。
你在这!您已成功发出请求,并收到了回复。通过检查内容,您可以判断它很可能是一个 HTML 文档。请注意,正文的打印输出前面有b。这表示一个bytes literal,您可能需要对其进行解码。在本教程的后面,您将学习如何将字节转换为字符串、将它们写入文件或将它们解析为字典。
如果您要调用 REST API 以获取 JSON 数据,则该过程仅略有不同。在下面的示例中,您将向{JSON}Placeholder请求一些虚假的待办事项数据:
from urllib.request import urlopen
import json
url = "https://jsonplaceholder.typicode.com/todos/1"
with urlopen(url) as response:
body = response.read()
todo_item = json.loads(body)
todo_item
{'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}
在此示例中,您所做的与上一个示例中的操作几乎相同。但在这一个中,您导入urllib.request and json,使用json.loads()函数 withbody将返回的 JSON 字节解码和解析为Python 字典。瞧!
如果您足够幸运能够使用无错误的端点,例如这些示例中的端点,那么也许以上就是您需要的全部urllib.request。话又说回来,您可能会发现这还不够。
现在,在进行一些urllib.request故障排除之前,您将首先了解 HTTP 消息的底层结构并了解如何urllib.request处理它们。这种理解将为解决许多不同类型的问题提供坚实的基础。
要了解您在使用 时可能遇到的一些问题,您urllib.request需要检查响应是如何由 表示的urllib.request。为此,您将受益于对HTTP 消息是什么的高级概述,这就是您将在本节中获得的内容。
在进行高级概述之前,先简要说明一下参考来源。如果您想深入了解技术领域,互联网工程任务组 (IETF)有大量的征求意见 (RFC)文档。这些文档最终成为 HTTP 消息之类的实际规范。例如, RFC 7230,第 1 部分:消息语法和路由都是关于 HTTP 消息的。
如果您正在寻找比 RFC 更容易理解的参考资料,那么Mozilla 开发者网络 (MDN)有大量参考文章。例如,他们关于HTTP 消息的文章虽然仍然是技术性的,但更容易理解。
现在您已经了解了这些基本的参考信息来源,在下一节中您将对 HTTP 消息有一个初学者友好的概述。
简而言之,HTTP 消息可以理解为文本,以字节流的形式传输,其结构遵循 RFC 7230 指定的准则。解码后的 HTTP 消息可以像两行一样简单:
GET / HTTP/1.1
Host: www.google.com
这使用协议在根 ( )指定GET请求。唯一需要的标头是主机,. 目标服务器有足够的信息来使用此信息做出响应。/HTTP/1.1www.google.com
响应在结构上类似于请求。HTTP 消息有两个主要部分,元数据和正文。在上面的请求示例中,消息是没有正文的所有元数据。另一方面,响应确实有两个部分:
HTTP/1.1 200 OK
Content-Type: text/html; charset=ISO-8859-1
Server: gws
(... other headers ...)
响应以指定 HTTP 协议和状态的状态行开始。在状态行之后,你会得到许多键值对,例如,代表所有的响应头。这是响应的元数据。HTTP/1.1200 OKServer: gws
在元数据之后,有一个空行,用作标题和正文之间的分隔符。空行之后的所有内容构成主体。这是您在使用urllib.request.
注意:空行在技术上通常称为 换行符 。HTTP 消息中的换行符必须是 Windows 样式的 回车符 ( \r ) 和 行尾 符( \n )。在 类 Unix 系统上,换行符通常只是一个行尾 ( \n )。
您可以假定所有 HTTP 消息都遵循这些规范,但有些消息可能会违反这些规则或遵循旧规范。不过,这很少会引起任何问题。因此,请将其牢记在心,以防遇到奇怪的错误!
在下一节中,您将了解如何urllib.request处理原始 HTTP 消息。
了解如何urllib.request表示 HTTP 消息
使用时您将与之交互的 HTTP 消息的主要表示urllib.request是HTTPResponse对象。urllib.request模块本身依赖于低级http模块,您不需要直接与之交互。不过,您确实最终会使用一些提供的数据结构http,例如HTTPResponse和HTTPMessage。
注意:在 Python 中表示 HTTP 响应和消息的对象的内部命名可能有点混乱。您通常只与 的实例进行交互HTTPResponse ,而请求端则在内部处理。
您可能认为这HTTPMessage 是一种HTTPResponse 继承自的基类,但事实并非如此。HTTPResponse 直接继承自io.BufferedIOBase ,而HTTPMessage 类继承自 email.message.EmailMessage 。
在源代码中将其EmailMessage 定义为包含一堆标头和有效负载的对象,因此它不一定是电子邮件。HTTPResponse 仅用HTTPMessage 作其标头的容器。
但是,如果您谈论的是 HTTP 本身而不是它的 Python 实现,那么您将 HTTP 响应视为一种 HTTP 消息是正确的。
当您使用 发出请求时urllib.request.urlopen(),您会得到一个HTTPResponse对象作为回报。花一些时间探索HTTPResponse对象pprint()并dir()查看属于它的所有不同方法和属性:
from urllib.request import urlopen
from pprint import pprint
with urlopen("https://www.example.com") as response:
pprint(dir(response))
要显示此代码片段的输出,请单击以展开下面的可折叠部分:
['__abstractmethods__',
'__class__',
'__del__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__enter__',
'__eq__',
'__exit__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__next__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'_abc_impl',
'_checkClosed',
'_checkReadable',
'_checkSeekable',
'_checkWritable',
'_check_close',
'_close_conn',
'_get_chunk_left',
'_method',
'_peek_chunked',
'_read1_chunked',
'_read_and_discard_trailer',
'_read_next_chunk_size',
'_read_status',
'_readall_chunked',
'_readinto_chunked',
'_safe_read',
'_safe_readinto',
'begin',
'chunk_left',
'chunked',
'close',
'closed',
'code',
'debuglevel',
'detach',
'fileno',
'flush',
'fp',
'getcode',
'getheader',
'getheaders',
'geturl',
'headers',
'info',
'isatty',
'isclosed',
'length',
'msg',
'peek',
'read',
'read1',
'readable',
'readinto',
'readinto1',
'readline',
'readlines',
'reason',
'seek',
'seekable',
'status',
'tell',
'truncate',
'url',
'version',
'will_close',
'writable',
'write',
'writelines']
这是很多方法和属性,但您最终只会使用其中的一小部分。除此之外.read(),重要的通常涉及获取有关标头的信息。
检查所有标头的一种方法是访问对象的.headers属性HTTPResponse。这将返回一个HTTPMessage对象。方便地,您可以HTTPMessage通过调用.items()它来将所有标头作为元组来对待它,就像字典一样:
with urlopen("https://www.example.com") as response:
pass
response.headers
pprint(response.headers.items())
[('Accept-Ranges', 'bytes'),
('Age', '398424'),
('Cache-Control', 'max-age=604800'),
('Content-Type', 'text/html; charset=UTF-8'),
('Date', 'Tue, 25 Jan 2022 12:18:53 GMT'),
('Etag', '"3147526947"'),
('Expires', 'Tue, 01 Feb 2022 12:18:53 GMT'),
('Last-Modified', 'Thu, 17 Oct 2019 07:18:26 GMT'),
('Server', 'ECS (nyb/1D16)'), ('Vary', 'Accept-Encoding'),
('X-Cache', 'HIT'),
('Content-Length', '1256'),
('Connection', 'close')]
现在您可以访问所有响应标头了!您可能不需要这些信息中的大部分,但请放心,某些应用程序确实会用到它。例如,您的浏览器可能会使用标头来读取响应、设置 cookie 并确定适当的缓存生存期。
有一些方便的方法可以从HTTPResponse对象中获取标头,因为这是很常见的操作。您可以.getheaders()直接调用该HTTPResponse对象,它将返回与上面完全相同的元组列表。如果您只对一个标题感兴趣,比如Server标题,那么您可以使用单数.getheader("Server")onHTTPResponse或使用方括号 ( []) 语法 on .headersfrom HTTPMessage:
>>> response.getheader("Server")
'ECS (nyb/1D16)'
>>> response.headers["Server"]
'ECS (nyb/1D16)'
说实话,您可能不需要像这样直接与标题进行交互。您最可能需要的信息可能已经有一些内置的辅助方法,但现在您知道了,以防您需要更深入地挖掘!
关闭一个HTTPResponse
该对象与文件对象HTTPResponse有很多共同之处。类继承自类,文件对象也是如此,这意味着您必须注意打开和关闭。HTTPResponseIOBase
在简单的程序中,如果您忘记关闭HTTPResponse对象,您不太可能注意到任何问题。但是,对于更复杂的项目,这会显着降低执行速度并导致难以查明的错误。
出现问题是因为输入/输出(I/O) 流是有限的。每个都HTTPResponse需要在读取时保持流清晰。如果您从不关闭您的流,这最终将阻止任何其他流被打开,并且它可能会干扰其他程序甚至您的操作系统。
所以,一定要关闭你的HTTPResponse对象!为方便起见,您可以使用上下文管理器,如您在示例中所见。您还可以通过显式调用.close()响应对象来获得相同的结果:
from urllib.request import urlopen
response = urlopen("https://www.example.com")
body = response.read()
response.close()
在此示例中,您不使用上下文管理器,而是显式关闭响应流。不过,上面的示例仍然存在问题,因为在调用 之前可能会引发异常.close(),从而阻止正确的拆解。为了使这个调用成为无条件的,就像它应该的那样,你可以使用带有一个和一个子句的try…except块:elsefinally
from urllib.request import urlopen
response = None
try:
response = urlopen("https://www.example.com")
except Exception as ex:
print(ex)
else:
body = response.read()
finally:
if response is not None:
response.close()
.close()在此示例中,您通过使用块实现了对 的无条件调用,finally无论是否引发异常,该块都将始终运行。块中的代码finally首先检查response对象是否存在is not None,然后将其关闭。
也就是说,这正是 aa 上下文管理器所做的,并且with语法通常是首选的。语法不仅with更简洁、更易读,而且还可以保护您免受讨厌的遗漏错误。换句话说,它可以更好地防止意外忘记关闭对象:
from urllib.request import urlopen
with urlopen("https://www.example.com") as response:
response.read(50)
response.read(50)
b'\n\n\n
Example D'b'omain \n\n \n
urlopen()在此示例中,您从urllib.request模块导入。您使用with关键字 with.urlopen()将HTTPResponse对象分配给变量response。然后,您读取响应的前五十个字节,然后读取后面的五十个字节,所有这些都在with块内。最后,您关闭with块,它执行请求并运行其块内的代码行。
使用此代码,您可以显示两组,每组 50 个字节。HTTPResponse一旦退出块范围,该对象将关闭with,这意味着该.read()方法将只返回空字节对象:
import urllib.request
with urllib.request.urlopen("https://www.example.com") as response:
response.read(50)
b'\n\n\n Example D'</code></pre>
<pre class="kdocs-python"><code class="language-python">response.read(50)</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext">b''</code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在此示例中,读取五十个字节的第二次调用超出了</span>with<span class="kdocs-fontSize" style="font-size:13pt;">范围。在</span>with<span class="kdocs-fontSize" style="font-size:13pt;">块之外意味着</span>HTTPResponse<span class="kdocs-fontSize" style="font-size:13pt;">关闭,即使您仍然可以访问该变量。如果您尝试从</span>HTTPResponse<span class="kdocs-fontSize" style="font-size:13pt;">它关闭时开始读取,它将返回一个空字节对象。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">另一点需要注意的是,一旦你一直阅读到最后,你就不能重新阅读回复:</span></p>
<pre class="kdocs-python"><code class="language-python">import urllib.request
with urllib.request.urlopen("https://www.example.com") as response:
first_read = response.read()
second_read = response.read()
len(first_read)</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext">1256</code></pre>
<pre class="kdocs-python"><code class="language-python">len(second_read)</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext">0</code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">这个例子表明,一旦你读过一个回复,你就不能再读了。如果您已完全阅读响应,即使响应未关闭,后续尝试也只会返回一个空字节对象。你必须再次提出请求。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在这方面,响应与文件对象不同,因为对于文件对象,您可以使用不支持的</span>.seek()<span class="kdocs-fontSize" style="font-size:13pt;">方法多次读取它。</span>HTTPResponse<span class="kdocs-fontSize" style="font-size:13pt;">即使在关闭响应后,您仍然可以访问标头和其他元数据。</span></p>
<h4 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">探索文本、八位字节和位</span></h4>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">到目前为止,在大多数示例中,您从 读取响应主体</span>HTTPResponse<span class="kdocs-fontSize" style="font-size:13pt;">,立即显示结果数据,并注意到它显示为</span><span class="kdocs-fontSize" style="font-size:13pt;">字节对象</span><span class="kdocs-fontSize" style="font-size:13pt;">。这是因为计算机中的文本信息不是以字母形式存储或传输的,而是以字节形式存储和传输的!</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">通过网络发送的原始 HTTP 消息被分解为</span><span class="kdocs-fontSize" style="font-size:13pt;">字节</span><span class="kdocs-fontSize" style="font-size:13pt;">序列,有时称为</span><span class="kdocs-fontSize" style="font-size:13pt;">八位字节</span><span class="kdocs-fontSize" style="font-size:13pt;">。字节是 8</span><span class="kdocs-fontSize" style="font-size:13pt;">位</span><span class="kdocs-fontSize" style="font-size:13pt;">块。例如,</span>01010101<span class="kdocs-fontSize" style="font-size:13pt;">是一个字节。要了解有关二进制、位和字节的更多信息,请查看</span><span class="kdocs-fontSize" style="font-size:13pt;">Python 中的位运算符</span><span class="kdocs-fontSize" style="font-size:13pt;">。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">那么如何用字节表示字母呢?一个字节有 256 种可能的组合,您可以为每种组合分配一个字母。您可以分配</span>00000001<span class="kdocs-fontSize" style="font-size:13pt;">给</span>A<span class="kdocs-fontSize" style="font-size:13pt;">、</span>00000010<span class="kdocs-fontSize" style="font-size:13pt;">给</span>B<span class="kdocs-fontSize" style="font-size:13pt;">等等。</span><span class="kdocs-fontSize" style="font-size:13pt;">相当普遍的ASCII</span><span class="kdocs-fontSize" style="font-size:13pt;">字符编码,使用这种系统编码128个字符,对于像英语这样的语言来说已经足够了。这是特别方便的,因为一个字节就可以表示所有的字符,还有空间。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">所有标准英语字符,包括大写字母、标点符号和数字,都适合 ASCII。另一方面,日语被认为有大约五万个符号字符,所以 128 个字符不够用!即使是理论上在一个字节内可用的 256 个字符对于日语来说也远远不够。因此,为了适应世界上所有的语言,有许多不同的字符编码系统。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">尽管有很多系统,但您可以信赖的一件事是它们总是被分解成<span class="kdocs-bold" style="font-weight:bold;">字节</span>。大多数服务器,如果无法解析</span><span class="kdocs-fontSize" style="font-size:13pt;">MIME 类型</span><span class="kdocs-fontSize" style="font-size:13pt;">和字符编码,默认为</span>application/octet-stream<span class="kdocs-fontSize" style="font-size:13pt;">,字面意思是字节流。然后谁收到消息就可以计算出字符编码。</span></p>
<h4 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">处理字符编码</span></h4>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">问题经常出现是因为,正如您可能已经猜到的那样,有很多很多不同的潜在字符编码。当今占主导地位的字符编码是</span><span class="kdocs-fontSize" style="font-size:13pt;">UTF-8</span><span class="kdocs-fontSize" style="font-size:13pt;">,它是</span><span class="kdocs-fontSize" style="font-size:13pt;">Unicode</span><span class="kdocs-fontSize" style="font-size:13pt;">的一种实现。幸运的是,今天</span><span class="kdocs-fontSize" style="font-size:13pt;">98% 的网页</span><span class="kdocs-fontSize" style="font-size:13pt;">都是用 UTF-8 编码的!</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">UTF-8 之所以占主导地位,是因为它可以有效地处理数量多得令人难以置信的字符。它处理 Unicode 定义的所有 1,112,064 个潜在字符,包括中文、日文、阿拉伯文(使用从右到左的脚本)、俄文和更多字符集,包括</span><span class="kdocs-fontSize" style="font-size:13pt;">表情符号</span><span class="kdocs-fontSize" style="font-size:13pt;">!</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">UTF-8 保持高效,因为它使用可变数量的字节来编码字符,这意味着对于许多字符,它只需要一个字节,而对于其他字符,它可能需要多达四个字节。</span></p>
<blockquote class="kdocs-blockquote" style=""> <span class="kdocs-fontSize" style="font-size:13pt;"><span class="kdocs-bold" style="font-weight:bold;">注意</span>:要了解有关 Python 中编码的更多信息,请查看 Python 中的</span> <span class="kdocs-fontSize" style="font-size:13pt;">Unicode 和字符编码:无痛指南</span> <span class="kdocs-fontSize" style="font-size:13pt;">。</span>
</blockquote>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">虽然 UTF-8 占主导地位,并且假设 UTF-8 编码通常不会出错,但您仍然会一直遇到不同的编码。好消息是,在使用</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">.</span></p>
<h4 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">从字节到字符串</span></h4>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">当您使用</span>urllib.request.urlopen()<span class="kdocs-fontSize" style="font-size:13pt;">时,响应的主体是一个字节对象。您可能想要做的第一件事是将字节对象转换为字符串。也许您想做一些</span><span class="kdocs-fontSize" style="font-size:13pt;">网页抓取</span><span class="kdocs-fontSize" style="font-size:13pt;">。为此,您需要<span class="kdocs-bold" style="font-weight:bold;">解码</span>字节。要用 Python 解码字节,您只需找出所使用的<span class="kdocs-bold" style="font-weight:bold;">字符编码</span>即可。编码,特别是指字符编码时,通常称为<span class="kdocs-bold" style="font-weight:bold;">字符集</span>。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">如前所述,在百分之九十八的情况下,默认使用 UTF-8 可能是安全的:</span></p>
<pre class="kdocs-python"><code class="language-python">from urllib.request import urlopen
with urlopen("https://www.example.com") as response:
body = response.read()
decoded_body = body.decode("utf-8")
print(decoded_body[:30])</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext"><!doctype html>
<html>
<head></code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在此示例中,您获取从返回的字节对象并使用字节对象的方法</span>response.read()<span class="kdocs-fontSize" style="font-size:13pt;">对其进行解码,并将其作为参数传入。当您</span><span class="kdocs-fontSize" style="font-size:13pt;">打印</span><span class="kdocs-fontSize" style="font-size:13pt;">时,您可以看到它现在是一个字符串。</span>.decode()utf-8<span class="kdocs-fontSize" style="font-size:13pt;"> </span>decoded_body</p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">也就是说,听之任之很少是一个好的策略。幸运的是,标头是获取字符集信息的好地方:</span></p>
<pre class="kdocs-python"><code class="language-python">from urllib.request import urlopen
with urlopen("https://www.example.com") as response:
body = response.read()
character_set = response.headers.get_content_charset()
character_set</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext">'utf-8'</code></pre>
<pre class="kdocs-python"><code class="language-python">decoded_body = body.decode(character_set)
print(decoded_body[:30])</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext"><!doctype html>
<html>
<head></code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在此示例中,您调用</span>.get_content_charset()<span class="kdocs-fontSize" style="font-size:13pt;">的</span>.headers<span class="kdocs-fontSize" style="font-size:13pt;">对象</span>response<span class="kdocs-fontSize" style="font-size:13pt;">并使用它进行解码。这是一种解析</span>Content-Type<span class="kdocs-fontSize" style="font-size:13pt;">标头的便捷方法,因此您可以轻松地将字节解码为文本。</span></p>
<h4 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">从字节到文件</span></h4>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">如果您想将字节解码为文本,现在就可以开始了。但是,如果您想将响应的主体写入文件怎么办?那么,你有两个选择:</span></p>
<ol start="1">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;text-align:left;"><p><span class="kdocs-fontSize" style="font-size:13pt;">将字节直接写入文件</span></p></li>
</ol>
<ol start="2">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;text-align:left;"><p><span class="kdocs-fontSize" style="font-size:13pt;">将字节解码为 Python 字符串,然后将字符串编码回文件</span></p></li>
</ol>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">第一种方法最直接,但第二种方法允许您根据需要更改编码。要更详细地了解文件操作,请查看 Real Python 的 Python</span><span class="kdocs-fontSize" style="font-size:13pt;">读写文件(指南)</span><span class="kdocs-fontSize" style="font-size:13pt;">。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">要将字节直接写入文件而无需解码,您需要内置</span>open()<span class="kdocs-fontSize" style="font-size:13pt;">函数,并且需要确保使用写入二进制模式:</span></p>
<pre class="kdocs-python"><code class="language-python">from urllib.request import urlopen
with urlopen("https://www.example.com") as response:
body = response.read()
with open("example.html", mode="wb") as html_file:
html_file.write(body)</code></pre>
<p style="">1256</p>
<p style="">使用open()inwb模式绕过解码或编码的需要,并将 HTTP 消息正文的字节转储到example.html文件中。写入操作后输出的数字表示已写入的字节数。就是这样!您已将字节直接写入文件,而无需编码或解码任何内容。</p>
<p style="">现在假设您有一个不使用 UTF-8 的 URL,但您希望将内容写入具有 UTF-8 的文件。为此,您首先要将字节解码为字符串,然后将字符串编码为文件,并指定字符编码。</p>
<p style="">Google 的主页似乎根据您所在的位置使用不同的编码。在欧洲和美国的大部分地区,它使用ISO-8859-1编码:</p>
<pre class="kdocs-python"><code class="language-python">from urllib.request import urlopen
with urlopen("https://www.google.com") as response:
body = response.read()
character_set = response.headers.get_content_charset()
character_set</code></pre>
<p style="">'ISO-8859-1'</p>
<pre class="kdocs-python"><code class="language-python">content = body.decode(character_set)
with open("google.html", encoding="utf-8", mode="w") as file:
file.write(content)</code></pre>
<p style="">14066</p>
<p style=""><span class="kdocs-fontSize" style="font-size:13pt;">在此代码中,您获得了响应字符集并使用它将字节对象解码为字符串。然后将字符串写入文件,使用 UTF-8 对其进行编码。</span></p>
<blockquote class="kdocs-blockquote" style=""> <span class="kdocs-fontSize" style="font-size:13pt;"><span class="kdocs-bold" style="font-weight:bold;">注意</span>:有趣的是,Google 似乎有多层检查,用于确定使用何种语言和编码为网页提供服务。这意味着您可以指定一个</span> Accept-Language <span class="kdocs-fontSize" style="font-size:13pt;">标头</span> <span class="kdocs-fontSize" style="font-size:13pt;">,这似乎会覆盖您的 IP 位置。</span> <span class="kdocs-fontSize" style="font-size:13pt;">用不同的Locale Identifiers</span> <span class="kdocs-fontSize" style="font-size:13pt;">试试,看看你能得到什么编码!</span>
</blockquote>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">写入文件后,您应该能够在浏览器或文本编辑器中打开生成的文件。大多数现代文本处理器都可以自动检测字符编码。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">如果存在编码错误并且您正在使用 Python 读取文件,那么您可能会收到错误消息:</span></p>
<pre class="kdocs-python"><code class="language-python">with open("encoding-error.html", mode="r", encoding="utf-8") as file:
lines = file.readlines()</code></pre>
<p style="">UnicodeDecodeError: </p>
<p style=""> 'utf-8' codec can't decode byte</p>
<p style=""><span class="kdocs-fontSize" style="font-size:13pt;">Python 显式停止进程并引发异常,但在显示文本的程序中,例如您正在查看此页面的浏览器,您可能会发现臭名昭著的</span><span class="kdocs-fontSize" style="font-size:13pt;">替换字符</span><span class="kdocs-fontSize" style="font-size:13pt;">:</span></p>
<div class="kdocs-line-container" style="display:flex;">
<div class="kdocs-img" style="flex-direction:column;max-width:100%;display:flex;width:220px;justify-content:center;align-items:center;height:auto;">
<div class="kdocs-img" style="padding-top:100.0%;height:0;"> <a href="http://img.e-com-net.com/image/info8/bdda9a50ecd94391877fffa8a15d5570.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/bdda9a50ecd94391877fffa8a15d5570.jpg" style="margin-left:;display:block;width:220px;margin-top:-100.0%;height:auto;;border:1px solid black;" width="220" height="220" alt="【Web Crawler】Python 的 urllib.request 用于 HTTP 请求_第1张图片"></a>
</div>
</div>
</div>
<p style="text-indent:1.4em;padding-left:2.8em;">替换字符</p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">带有白色问号 (�) 的黑色菱形、正方形 (□) 和矩形 (▯) 通常用作无法解码的字符的替代品。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">有时,解码似乎有效,但会导致无法理解的序列,例如<span class="kdocs-italic" style="font-style:italic;">æ–‡å—化ã '。</span>,这也表明使用了错误的字符集。在日本,他们甚至有一个词来表示由于字符编码问题而出现乱码的文本,</span><span class="kdocs-fontSize" style="font-size:13pt;">Mojibake</span><span class="kdocs-fontSize" style="font-size:13pt;">,因为这些问题在互联网时代开始时就困扰着他们。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">这样,您现在应该能够使用从</span>urlopen()<span class="kdocs-fontSize" style="font-size:13pt;">. 在下一节中,您将学习如何使用该</span>json<span class="kdocs-fontSize" style="font-size:13pt;">模块将字节解析为 Python 字典。</span></p>
<h4 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">从字节到字典</span></h4>
<p style="">对于application/json响应,您经常会发现它们不包含任何编码信息:</p>
<pre class="kdocs-python"><code class="language-python">from urllib.request import urlopen
with urlopen("https://httpbin.org/json") as response:
body = response.read()
character_set = response.headers.get_content_charset()
print(character_set)</code></pre>
<p style="">None</p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在此示例中,您使用</span><span class="kdocs-fontSize" style="font-size:13pt;">httpbin</span>json<span class="kdocs-fontSize" style="font-size:13pt;">的端点,该服务允许您试验不同类型的请求和响应。端点模拟返回 JSON 数据的典型 API。请注意,该方法在其响应中不返回任何内容。</span>json.get_content_charset()</p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">即使没有字符编码信息,也不会全部丢失。根据</span><span class="kdocs-fontSize" style="font-size:13pt;">RFC 4627</span><span class="kdocs-fontSize" style="font-size:13pt;">,UTF-8 的默认编码是规范的绝对<span class="kdocs-italic" style="font-style:italic;">要求</span></span>application/json<span class="kdocs-fontSize" style="font-size:13pt;">。这并不是说每个服务器都遵守规则,但一般来说,您可以假设如果传输 JSON,它几乎总是使用 UTF-8 编码。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">幸运的是,</span>json.loads()<span class="kdocs-fontSize" style="font-size:13pt;">在引擎盖下解码字节对象,甚至在它可以处理的不同</span><span class="kdocs-fontSize" style="font-size:13pt;">编码方面有一些回旋余地。</span><span class="kdocs-fontSize" style="font-size:13pt;">因此,</span>json.loads()<span class="kdocs-fontSize" style="font-size:13pt;">只要它们是有效的 JSON,就应该能够处理您抛给它的大多数字节对象:</span></p>
<pre class="kdocs-python"><code class="language-python">import json
json.loads(body)</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext">{'slideshow': {'author': 'Yours Truly', 'date': 'date of publication', 'slides': [{'title': 'Wake up to WonderWidgets!', 'type': 'all'}, {'items': ['Why <em>WonderWidgets</em> are great', 'Who <em>buys</em> WonderWidgets'], 'title': 'Overview', 'type': 'all'}], 'title': 'Sample Slide Show'}}</code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">如您所见,该</span>json<span class="kdocs-fontSize" style="font-size:13pt;">模块自动处理解码并生成 Python 字典。几乎所有 API 都以 JSON 形式返回键值信息,尽管您可能会遇到一些使用</span><span class="kdocs-fontSize" style="font-size:13pt;">XML</span><span class="kdocs-fontSize" style="font-size:13pt;">的旧 API 。为此,您可能需要查看</span><span class="kdocs-fontSize" style="font-size:13pt;">Roadmap to XML Parsers in Python</span><span class="kdocs-fontSize" style="font-size:13pt;">。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">有了它,您应该对字节和编码有足够的了解,以免造成危险!在下一节中,您将学习如何排除和修复您在使用</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">.</span></p>
<h3 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">常见urllib.request问题</span></h3>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">无论您是否使用,您都可能在万维网<span class="kdocs-italic" style="font-style:italic;">上</span>遇到多种问题</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">。在本节中,您将学习如何在开始时处理几个最常见的错误:</span><span class="kdocs-bold" style="font-weight:bold;">403</span><span class="kdocs-fontSize" style="font-size:13pt;"><span class="kdocs-bold" style="font-weight:bold;">错误</span>和<span class="kdocs-bold" style="font-weight:bold;">TLS/SSL 证书错误</span>。<span class="kdocs-bold" style="font-weight:bold;">不过,在查看这些特定错误</span>之前,您将首先了解如何在使用</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">.</span></p>
<h4 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">实施错误处理</span></h4>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在您将注意力转移到特定错误之前,提高您的代码优雅地处理各种错误的能力将会得到回报。Web 开发被错误所困扰,您可以投入大量时间来明智地处理错误。在这里,您将学习在使用</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">.</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">HTTP 状态代码</span><span class="kdocs-fontSize" style="font-size:13pt;">伴随着状态行中的每个响应。如果您可以在响应中读取状态代码,则请求已到达其目标。虽然这很好,但如果响应代码以 . 开头,您只能认为请求完全成功</span>2<span class="kdocs-fontSize" style="font-size:13pt;">。例如,</span>200<span class="kdocs-fontSize" style="font-size:13pt;">代表</span>201<span class="kdocs-fontSize" style="font-size:13pt;">成功的请求。如果状态代码是</span>404<span class="kdocs-fontSize" style="font-size:13pt;">或</span>500<span class="kdocs-fontSize" style="font-size:13pt;">,例如,出了点问题,</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">将引发</span>HTTPError<span class="kdocs-fontSize" style="font-size:13pt;">.</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">有时会发生错误,提供的 URL 不正确,或者由于其他原因无法建立连接。在这些情况下,</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">将引发</span>URLError<span class="kdocs-fontSize" style="font-size:13pt;">.</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">最后,有时服务器就是不响应。也许您的网络连接速度很慢,服务器已关闭,或者服务器被编程为忽略特定请求。为了解决这个问题,您可以在一定时间后将</span>timeout<span class="kdocs-fontSize" style="font-size:13pt;">参数传递</span>urlopen()<span class="kdocs-fontSize" style="font-size:13pt;">给 raise a 。</span>TimeoutError</p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">处理这些异常的第一步是捕获它们。您可以使用, , 和classes捕获…块中产生</span>urlopen()<span class="kdocs-fontSize" style="font-size:13pt;">的错误:</span>tryexceptHTTPErrorURLErrorTimeoutError</p>
<pre class="kdocs-python"><code class="language-python"># request.py
from urllib.error import HTTPError, URLError
from urllib.request import urlopen
def make_request(url):
try:
with urlopen(url, timeout=10) as response:
print(response.status)
return response.read(), response
except HTTPError as error:
print(error.status, error.reason)
except URLError as error:
print(error.reason)
except TimeoutError:
print("Request timed out")</code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">该函数</span>make_request()<span class="kdocs-fontSize" style="font-size:13pt;">将 URL 字符串作为参数,尝试使用 获取来自该 URL 的响应</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">,并在发生错误时捕获</span>HTTPError<span class="kdocs-fontSize" style="font-size:13pt;">引发的对象。如果 URL 错误,它会捕获一个</span>URLError<span class="kdocs-fontSize" style="font-size:13pt;">. 如果它没有任何错误地通过,它只会打印状态并返回一个包含正文和响应的元组。响应将在 之后关闭</span>return<span class="kdocs-fontSize" style="font-size:13pt;">。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">该函数还调用</span>urlopen()<span class="kdocs-fontSize" style="font-size:13pt;">一个</span>timeout<span class="kdocs-fontSize" style="font-size:13pt;">参数,这将导致</span>TimeoutError<span class="kdocs-fontSize" style="font-size:13pt;">在指定的秒数后引发 a 。十秒通常是等待响应的合适时间,尽管一如既往,这在很大程度上取决于您需要向其发出请求的服务器。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">现在您已准备好优雅地处理各种错误,包括但不限于您接下来将介绍的错误。</span></p>
<h4 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">处理403错误</span></h4>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">您现在将使用该</span>make_request()<span class="kdocs-fontSize" style="font-size:13pt;">函数向</span><span class="kdocs-fontSize" style="font-size:13pt;">httpstat.us</span><span class="kdocs-fontSize" style="font-size:13pt;">发出一些请求,这是一个用于测试的模拟服务器。此模拟服务器将返回具有您请求的状态代码的响应。例如,如果您向 发出请求</span>https://httpstat.us/200<span class="kdocs-fontSize" style="font-size:13pt;">,您应该会得到</span>200<span class="kdocs-fontSize" style="font-size:13pt;">回应。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">像 httpstat.us 这样的 API 用于确保您的应用程序可以处理它可能遇到的所有不同状态代码。httpbin 也有这个功能,但是 httpstat.us 有更全面的状态码选择。它甚至有</span><span class="kdocs-fontSize" style="font-size:13pt;">臭名昭著的半官方</span><span class="kdocs-fontSize" style="font-size:13pt;"> </span>418<span class="kdocs-fontSize" style="font-size:13pt;">状态代码,返回消息<span class="kdocs-italic" style="font-style:italic;">我是茶壶</span>!</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">要与</span>make_request()<span class="kdocs-fontSize" style="font-size:13pt;">您在上一节中编写的函数进行交互,请以交互模式运行脚本:</span></p>
<pre class="kdocs-shell"><code class="language-shell">$ python3 -i request.py</code></pre>
<p style=""><span class="kdocs-fontSize" style="font-size:13pt;">使用</span>-i<span class="kdocs-fontSize" style="font-size:13pt;">标志,此命令将以</span><span class="kdocs-fontSize" style="font-size:13pt;">交互模式</span><span class="kdocs-fontSize" style="font-size:13pt;">运行脚本。这意味着它将执行脚本,然后打开</span><span class="kdocs-fontSize" style="font-size:13pt;">Python REPL</span><span class="kdocs-fontSize" style="font-size:13pt;">,因此您现在可以调用刚刚定义的函数:</span></p>
<pre class="kdocs-python"><code class="language-python">>>> make_request("https://httpstat.us/200")
200
(b'200 OK', <http.client.HTTPResponse object at 0x0000023D612660B0>)
>>> make_request("https://httpstat.us/403")
403 Forbidden</code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在这里,您尝试了httpstat.us 的</span>200<span class="kdocs-fontSize" style="font-size:13pt;">和</span>403<span class="kdocs-fontSize" style="font-size:13pt;">端点。</span>200<span class="kdocs-fontSize" style="font-size:13pt;">端点按预期进行并返回响应主体和响应对象。</span>403<span class="kdocs-fontSize" style="font-size:13pt;">端点只是打印了错误消息并且没有返回任何内容,这也符合预期。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">状态意味着服务器理解请求但</span>403<span class="kdocs-fontSize" style="font-size:13pt;">不会满足它。这是您可能会遇到的常见错误,尤其是在网络抓取时。在许多情况下,您可以通过传递</span><span class="kdocs-fontSize" style="font-size:13pt;">User-Agent</span><span class="kdocs-fontSize" style="font-size:13pt;">标头来解决它。</span></p>
<blockquote class="kdocs-blockquote" style=""> <span class="kdocs-fontSize" style="font-size:13pt;"><span class="kdocs-bold" style="font-weight:bold;">注意</span>:有两个密切相关的 4xx 代码有时会引起混淆:</span>
<br> 401 未经授权
<br> 403 禁止
<br>401 <span class="kdocs-fontSize" style="font-size:13pt;">如果用户未被识别或登录并且必须执行某些操作以获得访问权限,例如登录或注册,服务器应该返回。</span>
<br>403 <span class="kdocs-fontSize" style="font-size:13pt;">如果用户已被充分识别但无权访问资源,则应返回该状态。例如,如果您登录到社交媒体帐户并尝试查看某人的私人资料页面,那么您可能会获得一个</span>403 <span class="kdocs-fontSize" style="font-size:13pt;">状态。</span>
<br> <span class="kdocs-fontSize" style="font-size:13pt;">也就是说,不要完全信任状态代码。错误存在并且在复杂的分布式服务中很常见。有些服务器不是模范公民!</span>
</blockquote>
<p style=""><span class="kdocs-fontSize" style="font-size:13pt;">服务器识别发出请求的人或对象的主要方法之一是检查</span>User-Agent<span class="kdocs-fontSize" style="font-size:13pt;">标头。发送的原始默认请求</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">如下:</span></p>
<pre class="kdocs-python"><code class="language-python">GET https://httpstat.us/403 HTTP/1.1
Accept-Encoding: identity
Host: httpstat.us
User-Agent: Python-urllib/3.10
Connection: close</code></pre>
<p style=""><span class="kdocs-fontSize" style="font-size:13pt;">请注意,它</span>User-Agent<span class="kdocs-fontSize" style="font-size:13pt;">被列为</span>Python-urllib/3.10<span class="kdocs-fontSize" style="font-size:13pt;">. 您可能会发现某些网站会尝试阻止网络抓取工具,而这</span>User-Agent<span class="kdocs-fontSize" style="font-size:13pt;">是毫无意义的。话虽如此,您可以设置自己的</span>User-Agent<span class="kdocs-fontSize" style="font-size:13pt;">with </span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">,但您需要稍微修改一下函数:</span></p>
<pre class="kdocs-python"><code class="language-python"> # request.py
from urllib.error import HTTPError, URLError
-from urllib.request import urlopen
+from urllib.request import urlopen, Request
-def make_request(url):
+def make_request(url, headers=None):
+ request = Request(url, headers=headers or {})
try:
- with urlopen(url, timeout=10) as response:
+ with urlopen(request, timeout=10) as response:
print(response.status)
return response.read(), response
except HTTPError as error:
print(error.status, error.reason)
except URLError as error:
print(error.reason)
except TimeoutError:
print("Request timed out")</code></pre>
<p style=""><span class="kdocs-fontSize" style="font-size:13pt;">要自定义随请求一起发送的标头,您首先必须</span>Request<span class="kdocs-fontSize" style="font-size:13pt;">使用 URL 实例化一个对象。此外,您可以传入</span><span class="kdocs-fontSize" style="font-size:13pt;">关键字参数</span><span class="kdocs-fontSize" style="font-size:13pt;">,</span>headers<span class="kdocs-fontSize" style="font-size:13pt;">它接受代表您希望包含的任何标题的标准字典。因此,不是将 URL 字符串直接传递给 ,而是传递</span>urlopen()<span class="kdocs-fontSize" style="font-size:13pt;">已</span>Request<span class="kdocs-fontSize" style="font-size:13pt;">使用 URL 和标头实例化的对象。</span></p>
<blockquote class="kdocs-blockquote" style=""> <span class="kdocs-fontSize" style="font-size:13pt;"><span class="kdocs-bold" style="font-weight:bold;">注意</span>:在上面的示例中,当</span>Request <span class="kdocs-fontSize" style="font-size:13pt;">实例化时,如果已定义标题,则需要将其传递给它。否则,传递一个空白对象,例如</span>{} <span class="kdocs-fontSize" style="font-size:13pt;">. 你不能通过</span>None <span class="kdocs-fontSize" style="font-size:13pt;">,因为这会导致错误。</span>
</blockquote>
<p style=""><span class="kdocs-fontSize" style="font-size:13pt;">要使用这个改进后的函数,请重新启动交互式会话,然后</span>make_request()<span class="kdocs-fontSize" style="font-size:13pt;">使用表示标头的字典作为参数进行调用:</span></p>
<pre class="kdocs-python"><code class="language-python">body, response = make_request(
"https://www.httpbin.org/user-agent",
{"User-Agent": "Real Python"}
)</code></pre>
<p style="">200</p>
<pre class="kdocs-python"><code class="language-python">body</code></pre>
<p style="">b'{\n "user-agent": "Real Python"\n}\n'</p>
<p style="">在此示例中,您向 httpbin 发出请求。在这里,您使用user-agent端点返回请求的User-Agent值。因为您使用 的自定义用户代理发出了请求Real Python,所以这就是返回的内容。</p>
<p style="">但是,有些服务器是严格的,只接受来自特定浏览器的请求。幸运的是,可以User-Agent在网络上找到标准字符串,包括通过用户代理数据库。它们只是字符串,因此您需要做的就是复制要模拟的浏览器的用户代理字符串,并将其用作User-Agent标头的值。</p>
<h4 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">修复 SSLCERTIFICATE_VERIFY_FAILED错误</span></h4>
<p style="">另一个常见错误是由于 Python 无法访问所需的安全证书。要模拟此错误,您可以使用badssl.com提供的一些具有已知错误 SSL 证书的模拟站点。您可以向其中之一发出请求,例如superfish.badssl.com,并亲身体验该错误:</p>
<pre class="kdocs-plaintext"><code class="language-plaintext">from urllib.request import urlopen
urlopen("https://superfish.badssl.com/")</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext">Traceback (most recent call last):
(...)
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED]
certificate verify failed: unable to get local issuer certificate (_ssl.c:997)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
(...)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED]
certificate verify failed: unable to get local issuer certificate (_ssl.c:997)></code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在这里,向具有已知错误 SSL 证书的地址发出请求将</span>CERTIFICATE_VERIFY_FAILED<span class="kdocs-fontSize" style="font-size:13pt;">导致</span>URLError<span class="kdocs-fontSize" style="font-size:13pt;">.</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">SSL 代表安全套接字层。这是用词不当,因为 SSL 已被弃用,取而代之的是 TLS,即</span><span class="kdocs-fontSize" style="font-size:13pt;">传输层安全</span><span class="kdocs-fontSize" style="font-size:13pt;">性。有时旧术语只是坚持!这是一种加密网络流量的方法,这样假设的侦听器就无法窃听通过线路传输的信息。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">现在,大多数网站地址的前面不是,</span>http://<span class="kdocs-fontSize" style="font-size:13pt;">而是<span class="kdocs-italic" style="font-style:italic;">s</span>代表<span class="kdocs-italic" style="font-style:italic;">安全</span>。</span><span class="kdocs-fontSize" style="font-size:13pt;">HTTPS</span><span class="kdocs-fontSize" style="font-size:13pt;">连接必须通过 TLS 加密。可以处理 HTTP 和 HTTPS 连接。</span>https://urllib.request</p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">HTTPS 的详细信息远远超出了本教程的范围,但您可以将 HTTPS 连接视为涉及两个阶段,即</span><span class="kdocs-fontSize" style="font-size:13pt;">握手</span><span class="kdocs-fontSize" style="font-size:13pt;">和信息传输。握手确保连接安全。有关 Python 和 HTTPS 的更多信息,请查看</span><span class="kdocs-fontSize" style="font-size:13pt;">使用 Python 探索 HTTPS</span><span class="kdocs-fontSize" style="font-size:13pt;">。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">为了确定特定服务器是安全的,发出请求的程序依赖于可信证书的存储。服务器的证书在握手阶段进行验证。Python 使用</span><span class="kdocs-fontSize" style="font-size:13pt;">操作系统的证书存储</span><span class="kdocs-fontSize" style="font-size:13pt;">。如果 Python 找不到系统的证书存储,或者存储已过期,那么您将遇到此错误。</span></p>
<blockquote class="kdocs-blockquote" style=""> <span class="kdocs-fontSize" style="font-size:13pt;"><span class="kdocs-bold" style="font-weight:bold;">注意</span>:在以前的 Python 版本中,默认行为</span>urllib.request <span class="kdocs-fontSize" style="font-size:13pt;">是<span class="kdocs-bold" style="font-weight:bold;">不</span>验证证书,这导致</span> <span class="kdocs-fontSize" style="font-size:13pt;">PEP 476</span> <span class="kdocs-fontSize" style="font-size:13pt;">默认启用证书验证。</span> <span class="kdocs-fontSize" style="font-size:13pt;">默认值在Python 3.4.3</span> <span class="kdocs-fontSize" style="font-size:13pt;">中更改。</span>
</blockquote>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">有时 Python 可以访问的证书存储已过时,或者 Python 无法访问它,无论出于何种原因。这是令人沮丧的,因为有时您可以从浏览器访问该 URL,它认为它是安全的,但</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">仍然会引发此错误。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">您可能想选择不验证证书,但这会使您的连接<span class="kdocs-italic" style="font-style:italic;">不安全</span>,绝对<span class="kdocs-italic" style="font-style:italic;">不推荐</span>:</span></p>
<pre class="kdocs-python"><code class="language-python">import ssl
from urllib.request import urlopen
unverified_context = ssl._create_unverified_context()
urlopen("https://superfish.badssl.com/", context=unverified_context)</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext"><http.client.HTTPResponse object at 0x00000209CBE8F220></code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在这里您导入</span>ssl<span class="kdocs-fontSize" style="font-size:13pt;">模块,它允许您创建一个</span><span class="kdocs-fontSize" style="font-size:13pt;">未验证的上下文</span><span class="kdocs-fontSize" style="font-size:13pt;">。然后,您可以将此上下文传递给</span>urlopen()<span class="kdocs-fontSize" style="font-size:13pt;">并访问已知的错误 SSL 证书。连接成功通过,因为未检查 SSL 证书。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在诉诸这些孤注一掷的措施之前,请尝试更新您的操作系统或更新您的 Python 版本。如果失败,那么您可以从</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">库中获取一个页面并安装</span>certifi<span class="kdocs-fontSize" style="font-size:13pt;">:</span></p>
<pre class="kdocs-shell"><code class="language-shell">$ python3 -m venv venv
$ source venv/bin/activate.sh
(venv) $ python3 -m pip install certifi</code></pre>
<p style="">certifi<span class="kdocs-fontSize" style="font-size:13pt;">是一个证书集合,您可以使用它来代替系统的集合。</span>certifi<span class="kdocs-fontSize" style="font-size:13pt;">您可以通过使用证书捆绑而不是操作系统的捆绑创建 SSL 上下文来执行此操作:</span></p>
<pre class="kdocs-python"><code class="language-python">import ssl
from urllib.request import urlopen
import certifi
certifi_context = ssl.create_default_context(cafile=certifi.where())
urlopen("https://sha384.badssl.com/", context=certifi_context)</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext"><http.client.HTTPResponse object at 0x000001C7407C3490></code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在此示例中,您曾经</span>certifi<span class="kdocs-fontSize" style="font-size:13pt;">充当 SSL 证书存储,并使用它成功连接到具有已知良好 SSL 证书的站点。请注意</span>._create_unverified_context()<span class="kdocs-fontSize" style="font-size:13pt;">,您使用的不是</span>.create_default_context()<span class="kdocs-fontSize" style="font-size:13pt;">。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">这样,您就可以保持安全而不会遇到太多麻烦!在下一节中,您将涉足身份验证的世界。</span></p>
<h3 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">经过身份验证的请求</span></h3>
<p style="text-align:left;">requests<span class="kdocs-fontSize" style="font-size:13pt;">身份验证是一个庞大的主题,如果您要处理的身份验证比此处介绍的内容复杂得多,那么这可能是进入该包的一个很好的起点。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在本教程中,您将只介绍一种身份验证方法,它作为您必须进行的调整类型的示例来验证您的请求。</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">确实有很多其他功能可以帮助进行身份验证,但本教程不会介绍这些功能。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">最常见的身份验证工具之一是不记名令牌,由</span><span class="kdocs-fontSize" style="font-size:13pt;">RFC 6750</span><span class="kdocs-fontSize" style="font-size:13pt;">指定。它通常用作</span><span class="kdocs-fontSize" style="font-size:13pt;">OAuth</span><span class="kdocs-fontSize" style="font-size:13pt;">的一部分,但也可以单独使用。它也是最常见的标题,您可以将其与当前</span>make_request()<span class="kdocs-fontSize" style="font-size:13pt;">函数一起使用:</span></p>
<pre class="kdocs-python"><code class="language-python">token = "abcdefghijklmnopqrstuvwxyz"
headers = {
"Authorization": f"Bearer {token}"
}
make_request("https://httpbin.org/bearer", headers)</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext">200
(b'{\n "authenticated": true, \n "token": "abcdefghijklmnopqrstuvwxyz"\n}\n',
<http.client.HTTPResponse object at 0x0000023D612642E0>)</code></pre>
<p style="text-align:left;">/bearer<span class="kdocs-fontSize" style="font-size:13pt;">在此示例中,您向模拟承载身份验证的 httpbin 端点发出请求。它会接受任何字符串作为标记。它只需要 RFC 6750 指定的正确格式。名称<span class="kdocs-italic" style="font-style:italic;">必须</span>是</span>Authorization<span class="kdocs-fontSize" style="font-size:13pt;">,有时是小写字母</span>authorization<span class="kdocs-fontSize" style="font-size:13pt;">,值<span class="kdocs-italic" style="font-style:italic;">必须</span>是</span>Bearer<span class="kdocs-fontSize" style="font-size:13pt;">,在它和标记之间有一个空格。</span></p>
<blockquote class="kdocs-blockquote" style=""> <span class="kdocs-fontSize" style="font-size:13pt;"><span class="kdocs-bold" style="font-weight:bold;">注意</span>:如果您使用任何形式的令牌或秘密信息,请务必妥善保护这些令牌。例如,不要将它们提交到 GitHub 存储库,而是将它们存储为临时</span> <span class="kdocs-fontSize" style="font-size:13pt;">环境变量</span> <span class="kdocs-fontSize" style="font-size:13pt;">。</span>
</blockquote>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">恭喜,您已使用不记名令牌成功通过身份验证!</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">另一种身份验证形式称为</span><span class="kdocs-fontSize" style="font-size:13pt;"><span class="kdocs-bold" style="font-weight:bold;">基本访问身份验证</span></span><span class="kdocs-fontSize" style="font-size:13pt;">,这是一种非常简单的身份验证方法,只比在标头中发送用户名和密码好一点。很没有安全感!</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">当今最常用的协议之一是</span><span class="kdocs-fontSize" style="font-size:13pt;"><span class="kdocs-bold" style="font-weight:bold;">OAuth(开放授权)</span></span><span class="kdocs-fontSize" style="font-size:13pt;">。如果您曾使用 Google、GitHub 或 Facebook 登录其他网站,那么您就使用过 OAuth。OAuth 流程通常涉及您要与之交互的服务和身份服务器之间的一些请求,从而产生一个短暂的不记名令牌。该持有者令牌随后可用于持有者身份验证一段时间。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">大部分身份验证归结为了解目标服务器使用的特定协议并仔细阅读文档以使其正常工作。</span></p>
<h3 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">POST 请求urllib.request</span></h3>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">您发出了很多 GET 请求,但有时您想要<span class="kdocs-italic" style="font-style:italic;">发送</span>信息。这就是 POST 请求的用武之地。要使用 发出 POST 请求</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">,您不必显式更改方法。您可以只将</span>data<span class="kdocs-fontSize" style="font-size:13pt;">对象传递给新</span>Request<span class="kdocs-fontSize" style="font-size:13pt;">对象或直接传递给</span>urlopen()<span class="kdocs-fontSize" style="font-size:13pt;">. 但是,该</span>data<span class="kdocs-fontSize" style="font-size:13pt;">对象必须采用特殊格式。您将</span>make_request()<span class="kdocs-fontSize" style="font-size:13pt;">通过添加参数稍微调整您的函数以支持 POST 请求</span>data<span class="kdocs-fontSize" style="font-size:13pt;">:</span></p>
<pre class="kdocs-python"><code class="language-python"># request.py
from urllib.error import HTTPError, URLError
from urllib.request import urlopen, Request
-def make_request(url, headers=None):
+def make_request(url, headers=None, data=None):
- request = Request(url, headers=headers or {})
+ request = Request(url, headers=headers or {}, data=data)
try:
with urlopen(request, timeout=10) as response:
print(response.status)
return response.read(), response
except HTTPError as error:
print(error.status, error.reason)
except URLError as error:
print(error.reason)
except TimeoutError:
print("Request timed out")</code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在这里,您只是修改了函数以接受</span>data<span class="kdocs-fontSize" style="font-size:13pt;">默认值为 的参数</span>None<span class="kdocs-fontSize" style="font-size:13pt;">,并将其直接传递到</span>Request<span class="kdocs-fontSize" style="font-size:13pt;">实例化中。不过,这还不是全部。您可以使用两种不同格式中的一种来执行 POST 请求:</span></p>
<ol start="1">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;"><p><span class="kdocs-bold" style="font-weight:bold;">表格数据</span>:application/x-www-form-urlencoded</p></li>
</ol>
<ol start="2">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;"><p><span class="kdocs-bold" style="font-weight:bold;">JSON</span>:application/json</p></li>
</ol>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">第一种格式是最古老的 POST 请求格式,涉及使用</span><span class="kdocs-fontSize" style="font-size:13pt;">百分比编码</span><span class="kdocs-fontSize" style="font-size:13pt;">对数据进行编码,也称为 URL 编码。</span><span class="kdocs-fontSize" style="font-size:13pt;">您可能已经注意到编码为查询字符串</span><span class="kdocs-fontSize" style="font-size:13pt;">的键值对 URL 。键与值用等号 ( </span>=<span class="kdocs-fontSize" style="font-size:13pt;">) 分隔,键值对用 & 符号 ( </span>&<span class="kdocs-fontSize" style="font-size:13pt;">) 分隔,空格通常被抑制但可以用加号 ( </span>+<span class="kdocs-fontSize" style="font-size:13pt;">) 代替。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">如果您从 Python 字典开始,要在您的</span>make_request()<span class="kdocs-fontSize" style="font-size:13pt;">函数中使用表单数据格式,您需要编码两次:</span></p>
<ol start="3">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;"><p>一次对字典进行 URL 编码</p></li>
</ol>
<ol start="4">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;"><p>然后再次将结果字符串编码为字节</p></li>
</ol>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">对于 URL 编码的第一阶段,您将使用另一个</span>urllib<span class="kdocs-fontSize" style="font-size:13pt;">模块</span>urllib.parse<span class="kdocs-fontSize" style="font-size:13pt;">. 请记住以交互模式启动您的脚本,以便您可以使用该</span>make_request()<span class="kdocs-fontSize" style="font-size:13pt;">函数并在 REPL 上运行它:</span></p>
<pre class="kdocs-python"><code class="language-python">from urllib.parse import urlencode
post_dict = {"Title": "Hello World", "Name": "Real Python"}
url_encoded_data = urlencode(post_dict)
url_encoded_data
# 'Title=Hello+World&Name=Real+Python'
post_data = url_encoded_data.encode("utf-8")
body, response = make_request(
"https://httpbin.org/anything", data=post_data
)
# 200
print(body.decode("utf-8"))</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext">{
"args": {},
"data": "",
"files": {},
"form": {
"Name": "Real Python",
"Title": "Hello World" },
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "34",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Python-urllib/3.10",
"X-Amzn-Trace-Id": "Root=1-61f25a81-03d2d4377f0abae95ff34096" },
"json": null,
"method": "POST",
"origin": "86.159.145.119",
"url": "https://httpbin.org/anything"}</code></pre>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在这个例子中,你:</span></p>
<ol start="5">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;"><p>urlencode()从urllib.parse模块导入</p></li>
</ol>
<ol start="6">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;"><p>初始化您的 POST 数据,从字典开始</p></li>
</ol>
<ol start="7">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;"><p>使用urlencode()函数对字典进行编码</p></li>
</ol>
<ol start="8">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;"><p>使用 UTF-8 编码将生成的字符串编码为字节</p></li>
</ol>
<ol start="9">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;"><p>向anything端点发出请求httpbin.org</p></li>
</ol>
<ol start="10">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;"><p>打印 UTF-8 解码的响应正文</p></li>
</ol>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">UTF-8 编码是类型</span><span class="kdocs-fontSize" style="font-size:13pt;">规范</span><span class="kdocs-fontSize" style="font-size:13pt;">的一部分</span>application/x-www-form-urlencoded<span class="kdocs-fontSize" style="font-size:13pt;">。UTF-8 被抢先用于解码正文,因为您已经知道</span>httpbin.org<span class="kdocs-fontSize" style="font-size:13pt;">可靠地使用 UTF-8。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">来自 httpbin的</span>anything<span class="kdocs-fontSize" style="font-size:13pt;">端点充当一种回显,返回它收到的所有信息,以便您可以检查您发出的请求的详细信息。在这种情况下,您可以确认</span>method<span class="kdocs-fontSize" style="font-size:13pt;">确实是</span>POST<span class="kdocs-fontSize" style="font-size:13pt;">,并且可以看到您发送的数据列在 下</span>form<span class="kdocs-fontSize" style="font-size:13pt;">。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">要使用 JSON 发出相同的请求,您将使用 将 Python 字典转换为 JSON 字符串</span>json.dumps()<span class="kdocs-fontSize" style="font-size:13pt;">,使用 UTF-8 对其进行编码,将其作为</span>data<span class="kdocs-fontSize" style="font-size:13pt;">参数传递,最后添加一个特殊的标头以指示数据类型为 JSON:</span></p>
<pre class="kdocs-python"><code class="language-python">post_dict = {"Title": "Hello World", "Name": "Real Python"}
import json
json_string = json.dumps(post_dict)
json_string</code></pre>
<p style="">'{"Title": "Hello World", "Name": "Real Python"}'</p>
<pre class="kdocs-python"><code class="language-python">post_data = json_string.encode("utf-8")
body, response = make_request(
"https://httpbin.org/anything",
data=post_data,
headers={"Content-Type": "application/json"},
)</code></pre>
<p style="">200</p>
<pre class="kdocs-python"><code class="language-python">print(body.decode("utf-8"))</code></pre>
<pre class="kdocs-plaintext"><code class="language-plaintext">{
"args": {},
"data": "{\"Title\": \"Hello World\", \"Name\": \"Real Python\"}",
"files": {},
"form": {},
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "47",
"Content-Type": "application/json",
"Host": "httpbin.org",
"User-Agent": "Python-urllib/3.10",
"X-Amzn-Trace-Id": "Root=1-61f25a81-3e35d1c219c6b5944e2d8a52"
},
"json": {
"Name": "Real Python",
"Title": "Hello World"
},
"method": "POST",
"origin": "86.159.145.119",
"url": "https://httpbin.org/anything"
}</code></pre>
<p style="">这次要序列化json.dumps()字典,您使用而不是urlencode(). 您还明确添加了Content-Type值为application/json. 有了这些信息,httpbin 服务器就可以在接收端反序列化 JSON。在其响应中,您可以看到json键下列出的数据。</p>
<blockquote class="kdocs-blockquote" style=""> <span class="kdocs-bold" style="font-weight:bold;">注意</span>:有时需要将 JSON 数据作为纯文本发送,在这种情况下,步骤与上述相同,只是您设置Content-Type为text/plain; charset=UTF-8. 许多这些必需品取决于您将数据发送到的服务器或 API,因此请务必阅读文档并进行实验!
</blockquote>
<p style="">这样,您现在就可以开始发出 POST 请求了。本教程不会详细介绍其他请求方法,例如PUT。可以这么说,您还可以通过将method关键字参数传递给Request对象的实例化来显式设置方法。</p>
<h3 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">请求包生态系统</span></h3>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">最后,本教程的最后一部分致力于阐明围绕使用 Python 的 HTTP 请求的包生态系统。因为包很多,没有明确的标准,容易造成混淆。也就是说,每个包都有用例,这就意味着你有更多的选择!</span></p>
<h4 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">urllib2和是什么urllib3?</span></h4>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">要回答这个问题,你需要回到早期的 Python,一路回到 1.2 版本,也就是最初</span>urllib<span class="kdocs-fontSize" style="font-size:13pt;">引入的时候。在 1.6 版左右,</span>urllib2<span class="kdocs-fontSize" style="font-size:13pt;">添加了一个修改版,它与原来的</span>urllib<span class="kdocs-fontSize" style="font-size:13pt;">. 当 Python 3 出现时,原来的</span>urllib<span class="kdocs-fontSize" style="font-size:13pt;">版本被弃用,并</span>urllib2<span class="kdocs-fontSize" style="font-size:13pt;">删除了</span>2<span class="kdocs-fontSize" style="font-size:13pt;">, 并采用了原来的</span>urllib<span class="kdocs-fontSize" style="font-size:13pt;">名称。它也分为几个部分:</span></p>
<ul>
<li style="margin-left:1.4em;list-style-type:disc;text-indent:0;text-align:left;"><p>urllib.error</p></li>
</ul>
<ul>
<li style="margin-left:1.4em;list-style-type:disc;text-indent:0;text-align:left;"><p>urllib.parse</p></li>
</ul>
<ul>
<li style="margin-left:1.4em;list-style-type:disc;text-indent:0;text-align:left;"><p>urllib.request</p></li>
</ul>
<ul>
<li style="margin-left:1.4em;list-style-type:disc;text-indent:0;text-align:left;"><p>urllib.response</p></li>
</ul>
<ul>
<li style="margin-left:1.4em;list-style-type:disc;text-indent:0;text-align:left;"><p>urllib.robotparser</p></li>
</ul>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">那么呢</span>urllib3<span class="kdocs-fontSize" style="font-size:13pt;">?</span>urllib2<span class="kdocs-fontSize" style="font-size:13pt;">那是仍然存在时开发的第三方库。它与标准库无关,因为它是一个独立维护的库。有趣的是,</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">图书馆实际上</span>urllib3<span class="kdocs-fontSize" style="font-size:13pt;">在幕后使用,所以</span>pip<span class="kdocs-fontSize" style="font-size:13pt;">!</span></p>
<h4 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">我应该什么时候使用requestsOver urllib.request?</span></h4>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">主要的答案是易用性和安全性。</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">被认为是一个低级库,它公开了很多关于 HTTP 请求工作的细节。的Python</span><span class="kdocs-fontSize" style="font-size:13pt;">文档</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">毫不含糊地推荐</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">作为更高级别的 HTTP 客户端接口。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">如果您日复一日地与许多不同的 REST API 进行交互,那么</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">强烈建议您使用。该</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">库标榜自己为“为人类而建”,并成功地围绕 HTTP 创建了一个直观、安全和直接的 API。它通常被认为是首选图书馆!如果您想了解有关该</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">库的更多信息,请查看 Real Python</span><span class="kdocs-fontSize" style="font-size:13pt;">指南</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">。</span></p>
<p style="text-align:left;">requests<span class="kdocs-fontSize" style="font-size:13pt;">如何让事情变得更简单的一个例子是字符编码。您会记得,使用 时</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">,您必须了解编码并采取一些步骤来确保无差错的体验。该</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">包将其抽象化,并将通过使用</span>chardet<span class="kdocs-fontSize" style="font-size:13pt;">通用字符编码检测器来解析编码,以防万一有任何有趣的事情。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">如果您的目标是了解有关标准 Python 的更多信息以及它如何处理 HTTP 请求的详细信息,那么这</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">是进入该领域的好方法。您甚至可以走得更远,使用非常低级的</span>http<span class="kdocs-fontSize" style="font-size:13pt;">模块</span><span class="kdocs-fontSize" style="font-size:13pt;">。另一方面,您可能只想将依赖性保持在最低限度,这</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">是完全可以做到的。</span></p>
<h4 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">为什么requests不是标准库的一部分?</span></h4>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">也许您想知道为什么</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">此时它还不是核心 Python 的一部分。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">这是一个复杂的问题,没有硬性的快速答案。关于原因有很多猜测,但似乎有两个原因很突出:</span></p>
<ol start="1">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;text-align:left;"><p>requests<span class="kdocs-fontSize" style="font-size:13pt;">还有其他需要集成的第三方依赖项。</span></p></li>
</ol>
<ol start="2">
<li style="margin-left:1.4em;list-style-type:decimal;text-indent:0;text-align:left;"><p>requests<span class="kdocs-fontSize" style="font-size:13pt;">需要保持敏捷并且可以在标准库之外做得更好。</span></p></li>
</ol>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">该</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">库具有第三方依赖项。集成</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">到标准库中还意味着集成</span>chardet<span class="kdocs-fontSize" style="font-size:13pt;">、</span>certifi<span class="kdocs-fontSize" style="font-size:13pt;">、 和</span>urllib3<span class="kdocs-fontSize" style="font-size:13pt;">等。另一种方法是从根本上改变</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">为仅使用 Python 现有的标准库。这不是一项简单的任务!</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">集成</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">还意味着开发该库的现有团队将不得不放弃对设计和实施的完全控制,让位于</span><span class="kdocs-fontSize" style="font-size:13pt;">PEP</span><span class="kdocs-fontSize" style="font-size:13pt;">决策过程。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">HTTP 规范和建议一直在变化,高级库必须足够敏捷才能跟上。如果有一个安全漏洞需要修补,或者有一个新的工作流程需要添加,</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">团队可以比他们作为 Python 发布过程的一部分更快地构建和发布。据推测,有时他们会在发现漏洞后十二小时发布安全修复程序!</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">有关这些问题和更多问题的有趣概述,请查看</span><span class="kdocs-fontSize" style="font-size:13pt;">将请求添加到标准库</span><span class="kdocs-fontSize" style="font-size:13pt;">,它总结了在 Python 语言峰会上与Requests 的创建者和维护者</span><span class="kdocs-fontSize" style="font-size:13pt;">Kenneth Reitz的讨论。</span></p>
<p style="text-align:left;">requests<span class="kdocs-fontSize" style="font-size:13pt;">因为这种敏捷性对于它及其底层是如此必要,所以经常使用对于标准库来说太重要</span>urllib3<span class="kdocs-fontSize" style="font-size:13pt;">的自相矛盾的陈述。</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">这是因为 Python 社区的大部分依赖</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">及其敏捷性,将其集成到核心 Python 中可能会损害它和 Python 社区。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">在 GitHub 存储库问题板上</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">,发布了一个问题,要求将 包含</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">在标准库</span><span class="kdocs-fontSize" style="font-size:13pt;">中。和的开发人员</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">插话</span>urllib3<span class="kdocs-fontSize" style="font-size:13pt;">,主要是说他们可能会对自己维护它失去兴趣。有些人甚至表示他们会分叉存储库并继续为他们自己的用例开发它们。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">话虽如此,请注意</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">库 GitHub 存储库托管在 Python 软件基金会的帐户下。仅仅因为某些东西不是 Python 标准库的一部分并不意味着它不是生态系统不可或缺的一部分!</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">目前的情况似乎对 Python 核心团队和</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">. 虽然对于新手来说可能有点混乱,但现有结构为 HTTP 请求提供了最稳定的体验。</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">同样重要的是要注意 HTTP 请求本质上是复杂的。</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">不要试图粉饰太多。它公开了 HTTP 请求的许多内部工作原理,这就是为什么它被标榜为低级模块的原因。您的选择实际上取决于您的特定用例、安全问题和偏好</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">。</span>urllib.request</p>
<h3 style="text-align:left;"><span class="kdocs-bold" style="font-weight:bold;">结论</span></h3>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">您现在已准备好使用它</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">来发出 HTTP 请求。现在您可以在您的项目中使用这个内置模块,让它们更长时间地保持无依赖性。您还通过使用较低级别的模块(例如</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">.</span></p>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;"><span class="kdocs-bold" style="font-weight:bold;">在本教程中,您已经:</span></span></p>
<ul>
<li style="margin-left:1.4em;list-style-type:disc;text-indent:0;"><p>学习了如何发出基本的<span class="kdocs-bold" style="font-weight:bold;">HTTP 请求</span>urllib.request</p></li>
</ul>
<ul>
<li style="margin-left:1.4em;list-style-type:disc;text-indent:0;"><p>探究了<span class="kdocs-bold" style="font-weight:bold;">HTTP 消息</span>的具体细节并研究了它是如何由urllib.request</p></li>
</ul>
<ul>
<li style="margin-left:1.4em;list-style-type:disc;text-indent:0;"><p>弄清楚如何处理HTTP 消息的字符<span class="kdocs-bold" style="font-weight:bold;">编码</span></p></li>
</ul>
<ul>
<li style="margin-left:1.4em;list-style-type:disc;text-indent:0;"><p>探索了一些使用中<span class="kdocs-bold" style="font-weight:bold;">的常见错误</span>,urllib.request并学习了如何解决这些错误</p></li>
</ul>
<ul>
<li style="margin-left:1.4em;list-style-type:disc;text-indent:0;"><p>将您的脚趾浸入经过<span class="kdocs-bold" style="font-weight:bold;">身份验证的请求</span>的世界urllib.request</p></li>
</ul>
<ul>
<li style="margin-left:1.4em;list-style-type:disc;text-indent:0;"><p>理解为什么两者urllib和requests库都存在以及<span class="kdocs-bold" style="font-weight:bold;">何时使用其中一个或另一个</span></p></li>
</ul>
<p style="text-align:left;"><span class="kdocs-fontSize" style="font-size:13pt;">您现在可以使用 发出基本的 HTTP 请求</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">,并且您还拥有使用标准库深入研究低级 HTTP 领域的工具。最后,您可以根据自己的需要选择是否使用</span>requests<span class="kdocs-fontSize" style="font-size:13pt;">或。</span>urllib.request<span class="kdocs-fontSize" style="font-size:13pt;">享受探索网络的乐趣!</span></p>
</div>
</div>
</div>
</div>
</div>
</div>
<!--PC和WAP自适应版-->
<div id="SOHUCS" sid="1735423176713756672"></div>
<script type="text/javascript" src="/views/front/js/chanyan.js"></script>
<!-- 文章页-底部 动态广告位 -->
<div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
</div>
<div class="col-md-3">
<div class="row" id="ad">
<!-- 文章页-右侧1 动态广告位 -->
<div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
<div class="youdao-fixed-ad" id="detail_ad_1"> </div>
</div>
<!-- 文章页-右侧2 动态广告位 -->
<div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
<div class="youdao-fixed-ad" id="detail_ad_2"></div>
</div>
<!-- 文章页-右侧3 动态广告位 -->
<div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
<div class="youdao-fixed-ad" id="detail_ad_3"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(网络爬虫(Web,Crawler),python,http,开发语言)</h4>
<div id="paradigm-article-related">
<div class="recommend-post mb30">
<ul class="widget-links">
<li><a href="/article/1892428190115229696.htm"
title="FOKS-TROT: 一个高效、易用的全功能开源知识图谱生成工具" target="_blank">FOKS-TROT: 一个高效、易用的全功能开源知识图谱生成工具</a>
<span class="text-muted">柳旖岭</span>
<div>FOKS-TROT:一个高效、易用的全功能开源知识图谱生成工具项目简介FOKS-TROT是一个基于Python的全功能开源知识图谱生成工具,旨在帮助研究人员和开发者快速构建具有丰富信息的知识图谱。该项目由hkx3upper在GitCode上开发并维护。通过FOKS-TROT,您可以轻松地将各种数据源(如文本文件、数据库、API)转换为结构化的知识图谱,并对其进行可视化分析和机器学习任务。此外,该工</div>
</li>
<li><a href="/article/1892427427007754240.htm"
title="PSINS工具箱函数介绍——ggnss(ggpsvars+gbdvars+gglovars)" target="_blank">PSINS工具箱函数介绍——ggnss(ggpsvars+gbdvars+gglovars)</a>
<span class="text-muted">MATLAB卡尔曼</span>
<a class="tag" taget="_blank" href="/search/PSINS%E5%87%BD%E6%95%B0/1.htm">PSINS函数</a><a class="tag" taget="_blank" href="/search/matlab/1.htm">matlab</a><a class="tag" taget="_blank" href="/search/PSINS/1.htm">PSINS</a>
<div>文章目录关于工具箱工具箱概述学习路径指南GNSS参数初始化函数`ggnss`函数功能参数体系结构典型应用场景系统参数初始化操作指南执行流程运行结果解析函数源码深度解析代码架构扩展开发建议关于工具箱kfinit是kf的参数初始化函数,用于初始化滤波参数本文所述的代码需要基于PSINS工具箱,工具箱的讲解:PSINS初学指导:https://blog.csdn.net/callmeup/article</div>
</li>
<li><a href="/article/1892427427712397312.htm"
title="python实现word文档合并 v2.0" target="_blank">python实现word文档合并 v2.0</a>
<span class="text-muted">task138</span>
<a class="tag" taget="_blank" href="/search/python%E8%87%AA%E5%8A%A8%E5%8C%96/1.htm">python自动化</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E5%8A%A8%E5%8C%96/1.htm">自动化</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4%E5%BC%80%E5%8F%91/1.htm">运维开发</a>
<div>目录前言要求运行效果脚本下载链接前言之前发表了一个小工具,python用于合并word文档以完成特定的工作任务,现在领导给出了新需求,适当的调整了一下word文档的合并情况。同时,各位同事反馈说,环境部署太难了,脚本的使用成本比较高,难度大,所以我这次把脚本打包成一个EXE可执行文件,直接双击即可使用。要求由于脚本的具体逻辑发生了变化,因此,exe文件的同级目录下,一定要存在一个txt文件,否则无</div>
</li>
<li><a href="/article/1892426922990825472.htm"
title="[附源码]计算机毕业设计基于SpringBoot的小说阅读系统" target="_blank">[附源码]计算机毕业设计基于SpringBoot的小说阅读系统</a>
<span class="text-muted">计算机毕设程序设计</span>
<a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a>
<div>项目运行环境配置:Jdk1.8+Tomcat7.0+Mysql+HBuilderX(Webstorm也行)+Eclispe(IntelliJIDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:SSM+mybatis+Maven+Vue等等组成,B/S模式+Maven管理等等。环境需要1.运行环境:最好是javajdk1.8,我们在这个平台上运行的。其他版本理论上也可以。2.ID</div>
</li>
<li><a href="/article/1892424906675646464.htm"
title="认识Spring IoC容器和组件" target="_blank">认识Spring IoC容器和组件</a>
<span class="text-muted">Mr_Zerone</span>
<a class="tag" taget="_blank" href="/search/SpringFramework/1.htm">SpringFramework</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a>
<div>1.传统Web项目开发流程传统Web项目在实现业务流程时,往往需要将Controller/Service/Dao,这三层先分别创建一个全局属性,上图中用BookController/BookService/BookDao来具体说明。当浏览器发送过来请求时,我们先调用全局属性中的BookCotroller对象bookController,在bookController中引用全局属性中的BookSer</div>
</li>
<li><a href="/article/1892423267881381888.htm"
title="安装配置MAVEN" target="_blank">安装配置MAVEN</a>
<span class="text-muted">ByteVoyager</span>
<a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
<div>安装配置MAVEN1.获取安装包下载apache-maven-3.8.1-bin.zip,下载地址:https://archive.apache.org/dist/maven/maven-3/3.8.1/binaries/apache-maven-3.8.1-bin.zip。2.解压maven压缩包3.配置maven环境变量新建环境变量MAVEN_HOME:右击【此电脑】->【属性】->【高级系统</div>
</li>
<li><a href="/article/1892422132458123264.htm"
title="蓝队基础:企业网络安全架构与防御策略" target="_blank">蓝队基础:企业网络安全架构与防御策略</a>
<span class="text-muted">重生之物联网转网安</span>
<a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8/1.htm">网络安全</a><a class="tag" taget="_blank" href="/search/%E5%AE%89%E5%85%A8/1.htm">安全</a>
<div>声明学习视频来自B站up主**泷羽sec**有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,此文章为对视频内容稍加整理发布,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关,切勿触碰法律底线,否则后果自负!!!!有兴趣的小伙伴可以点击下面连接进入b站主页[B站泷羽sec](https://space.bilibili.com/35032</div>
</li>
<li><a href="/article/1892421248793767936.htm"
title="2025年全国CTF夺旗赛-从零基础入门到竞赛,看这一篇就稳了!" target="_blank">2025年全国CTF夺旗赛-从零基础入门到竞赛,看这一篇就稳了!</a>
<span class="text-muted">白帽安全-黑客4148</span>
<a class="tag" taget="_blank" href="/search/%E5%AE%89%E5%85%A8/1.htm">安全</a><a class="tag" taget="_blank" href="/search/web%E5%AE%89%E5%85%A8/1.htm">web安全</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8/1.htm">网络安全</a><a class="tag" taget="_blank" href="/search/CTF/1.htm">CTF</a>
<div>目录一、CTF简介二、CTF竞赛模式三、CTF各大题型简介四、CTF学习路线4.1、初期1、html+css+js(2-3天)2、apache+php(4-5天)3、mysql(2-3天)4、python(2-3天)5、burpsuite(1-2天)4.2、中期1、SQL注入(7-8天)2、文件上传(7-8天)3、其他漏洞(14-15天)4.3、后期五、CTF学习资源5.1、CTF赛题复现平台5.</div>
</li>
<li><a href="/article/1892421249762652160.htm"
title="2025年全国CTF夺旗赛-从零基础入门到竞赛,看这一篇就稳了!" target="_blank">2025年全国CTF夺旗赛-从零基础入门到竞赛,看这一篇就稳了!</a>
<span class="text-muted">白帽安全-黑客4148</span>
<a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8/1.htm">网络安全</a><a class="tag" taget="_blank" href="/search/web%E5%AE%89%E5%85%A8/1.htm">web安全</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/%E5%AF%86%E7%A0%81%E5%AD%A6/1.htm">密码学</a><a class="tag" taget="_blank" href="/search/CTF/1.htm">CTF</a>
<div>目录一、CTF简介二、CTF竞赛模式三、CTF各大题型简介四、CTF学习路线4.1、初期1、html+css+js(2-3天)2、apache+php(4-5天)3、mysql(2-3天)4、python(2-3天)5、burpsuite(1-2天)4.2、中期1、SQL注入(7-8天)2、文件上传(7-8天)3、其他漏洞(14-15天)4.3、后期五、CTF学习资源5.1、CTF赛题复现平台5.</div>
</li>
<li><a href="/article/1892419989684678656.htm"
title="基于python深度学习遥感影像地物分类与目标识别、分割实践技术应用" target="_blank">基于python深度学习遥感影像地物分类与目标识别、分割实践技术应用</a>
<span class="text-muted">xiao5kou4chang6kai4</span>
<a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E9%81%A5%E6%84%9F/1.htm">遥感</a><a class="tag" taget="_blank" href="/search/%E5%8B%98%E6%B5%8B/1.htm">勘测</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E7%B1%BB/1.htm">分类</a>
<div>专题一:深度学习发展与机器学习深度学习的历史发展过程机器学习,深度学习等任务的基本处理流程梯度下降算法讲解不同初始化,学习率对梯度下降算法的实例分析从机器学习到深度学习算法专题二深度卷积网络、卷积神经网络、卷积运算的基本原理池化操作,全连接层,以及分类器的作用BP反向传播算法的理解一个简单CNN模型代码理解特征图,卷积核可视化分析专题三TensorFlow与keras介绍与入门TensorFlow</div>
</li>
<li><a href="/article/1892419231077691392.htm"
title="python 快速实现链接转 word 文档" target="_blank">python 快速实现链接转 word 文档</a>
<span class="text-muted">嘿嘿潶黑黑</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/word/1.htm">word</a>
<div>python快速实现链接转word文档演示代码展示最后演示代码展示fromnewspaperimportArticlefromdocximportDocumentfromdocx.sharedimportPt,RGBColorfromdocx.enum.styleimportWD_STYLE_TYPEfromdocx.oxml.nsimportqn#tkinterGUIimporttkintera</div>
</li>
<li><a href="/article/1892415698903298048.htm"
title="Python入门笔记" target="_blank">Python入门笔记</a>
<span class="text-muted">「已注销」</span>
<a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97%E6%9C%BA/1.htm">计算机</a>
<div>文章目录第0周课程导学第1周Python基本语法元素保留字数据类型语句与函数输入函数第2周Python基本图形绘制turtle库绝对坐标海龟坐标turtle角度坐标体系RGB色彩体系画笔控制函数运动控制函数方向控制函数循环语句第3周基本数据类型整型浮点数科学计数法复数类型数值运算操作符二元操作符有对应的增强赋值操作符数值运算函数字符串类型的表示字符串切片字符串类型及操作字符串类型格式化time库时</div>
</li>
<li><a href="/article/1892413431072485376.htm"
title="Redis主从复制" target="_blank">Redis主从复制</a>
<span class="text-muted">小松聊PHP进阶</span>
<a class="tag" taget="_blank" href="/search/Redis/1.htm">Redis</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a><a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a><a class="tag" taget="_blank" href="/search/nosql/1.htm">nosql</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a>
<div>主从复制官方文档:https://redis.io/docs/latest/operate/oss_and_stack/management/replication/极简概括:将一个主Redis服务器的数据复制到其它从Redis服务器的过程。角色:主节点(Master):负责处理客户端的写(或者读)请求,并将写操作同步到从节点。从节点(Slave):负责处理客户端的读请求,并将主节点发送过来的数据</div>
</li>
<li><a href="/article/1892412673446965248.htm"
title="pythonxml模块高级用法_Python minidom模块用法示例【DOM写入和解析XML】" target="_blank">pythonxml模块高级用法_Python minidom模块用法示例【DOM写入和解析XML】</a>
<span class="text-muted">Lucy-露西娅</span>
<a class="tag" taget="_blank" href="/search/pythonxml%E6%A8%A1%E5%9D%97%E9%AB%98%E7%BA%A7%E7%94%A8%E6%B3%95/1.htm">pythonxml模块高级用法</a>
<div>本文实例讲述了Pythonminidom模块用法。分享给大家供大家参考,具体如下:一、DOM写XML文件#-*-coding:utf-8-*-#!python3#导入minidomfromxml.domimportminidom#1.创建DOM树对象dom=minidom.Document()#2.创建根节点。每次都要用DOM对象来创建任何节点。root_node=dom.createElemen</div>
</li>
<li><a href="/article/1892411162377646080.htm"
title="Android Gradle使用总结" target="_blank">Android Gradle使用总结</a>
<span class="text-muted">Wei_Leng</span>
<a class="tag" taget="_blank" href="/search/Android/1.htm">Android</a><a class="tag" taget="_blank" href="/search/studio/1.htm">studio</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/gradle/1.htm">gradle</a><a class="tag" taget="_blank" href="/search/%E8%84%9A%E6%9C%AC/1.htm">脚本</a>
<div>其他Groovy入门学习http://blog.csdn.net/zhaoyanjun6/article/details/70313790AndroidGradleAndroid项目使用Gradle作为构建框架,Gradle又是以Groovy为脚本语言。所以学习Gradle之前需要先熟悉Groovy脚本语言。Groovy是基于Java语言的脚本语言,所以它的语法和Java非常相似,但是具有比jav</div>
</li>
<li><a href="/article/1892410529520087040.htm"
title="JavaScript的魔法世界:巧妙之处与实战技巧" target="_blank">JavaScript的魔法世界:巧妙之处与实战技巧</a>
<span class="text-muted">skyksksksksks</span>
<a class="tag" taget="_blank" href="/search/%E7%BB%BC%E5%90%88%E4%B8%AA%E4%BA%BA%E6%9D%82%E8%AE%B0/1.htm">综合个人杂记</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/html5/1.htm">html5</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
<div>一、从浏览器玩具到全栈利器的蜕变之路JavaScript诞生于1995年,原本只是网景公司为浏览器设计的"小脚本"。谁能想到这个曾被戏称为"玩具语言"的家伙,如今已蜕变成支撑现代Web开发的擎天柱?就像一只破茧成蝶的幼虫,JavaScript经历了ECMAScript标准的持续进化,在Node.js的加持下突破了浏览器的桎梏,实现了从客户端到服务端的华丽转身。V8引擎的涡轮增压让它跑得比猎豹还快,</div>
</li>
<li><a href="/article/1892410530585440256.htm"
title="EDA事件驱动架构 领域事件 Event Sourcing" target="_blank">EDA事件驱动架构 领域事件 Event Sourcing</a>
<span class="text-muted">talentluke</span>
<a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/1.htm">架构设计</a>
<div>摘自http://www.jdon.com/eda.htmlEDA(Event-drivenarchitecture)是以事件为核心,与SOA以服务为核心有本质区别,是状态模式的延伸到架构上,事件是触发状态变化的根源,事件是介于业务和技术两者之间的概念,用户界面是事件主要发生来源,事件也可以来源其他系统或模块,通过事件可以实现系统或组件之间松耦合。EDA可以实现SOA服务之间的调用,事件也可以用于</div>
</li>
<li><a href="/article/1892407248836161536.htm"
title="uniapp 使用web-view 来套地址实现分离式打包" target="_blank">uniapp 使用web-view 来套地址实现分离式打包</a>
<span class="text-muted">luckycoke</span>
<a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
<div>exportdefault{data(){return{title:'http://www.baidu.cn/'//你可以根据需要替换成你的URL};},mounted(){//在应用启动时清除本地缓存this.clearAppCache();},methods:{clearAppCache(){if(uni.getSystemInfoSync().platform==='android'){//</div>
</li>
<li><a href="/article/1892404728181092352.htm"
title="React 渲染 Flash 接口数据" target="_blank">React 渲染 Flash 接口数据</a>
<span class="text-muted">ox0080</span>
<a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/%E5%8C%97%E6%BC%82%2B%E6%BB%B4%E6%BB%B4%E5%87%BA%E8%A1%8C/1.htm">北漂+滴滴出行</a><a class="tag" taget="_blank" href="/search/VIP/1.htm">VIP</a><a class="tag" taget="_blank" href="/search/%E6%BF%80%E5%8A%B1/1.htm">激励</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a>
<div>1.后端Python代码使用Flask创建多个接口,每个接口返回不同的数据,并使用自定义装饰器来绑定路由。代码:#app.pyfromflaskimportFlask,jsonifyapp=Flask(__name__)defapi_route(route,methods=['GET']):"""自定义装饰器,用于将函数与HTTP路由绑定"""defdecorator(func):app.rout</div>
</li>
<li><a href="/article/1892402708804071424.htm"
title="LQB---基础练习---十六进制转八进制" target="_blank">LQB---基础练习---十六进制转八进制</a>
<span class="text-muted">「已注销」</span>
<a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/LQB/1.htm">LQB</a><a class="tag" taget="_blank" href="/search/LQB/1.htm">LQB</a>
<div>试题基础练习十六进制转八进制资源限制内存限制:512.0MBC/C++时间限制:1.0sJava时间限制:3.0sPython时间限制:5.0s问题描述给定n个十六进制正整数,输出它们对应的八进制数。输入格式输入的第一行为一个正整数n(1<=n<=10)。接下来n行,每行一个由09、大写字母AF组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。输出格式输出n行,每行为</div>
</li>
<li><a href="/article/1892400189780586496.htm"
title="js如何直接下载文件流" target="_blank">js如何直接下载文件流</a>
<span class="text-muted">涔溪</span>
<a class="tag" taget="_blank" href="/search/js/1.htm">js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
<div>在JavaScript中直接处理文件下载,尤其是在处理文件流的情况下,通常涉及到使用fetchAPI或者XMLHttpRequest来获取文件流,并通过创建一个临时的标签(锚点元素)触发下载。以下是使用fetchAPI的一个示例:fetch('你的文件URL',{method:'GET',headers:{//如果需要的话,可以在这里添加请求头}}).then(response=>response</div>
</li>
<li><a href="/article/1892399055670145024.htm"
title="六、soul源码学习-SpringCloud项目本地运行" target="_blank">六、soul源码学习-SpringCloud项目本地运行</a>
<span class="text-muted">caihuayuan4</span>
<a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB%E4%B8%8E%E8%A7%A3%E6%9E%90/1.htm">面试题汇总与解析</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a>
<div>一、本地部署NacosNacos本地部署可以参考:http://www.iocoder.cn/Nacos/install/?self二、搭建SpringCloud项目示例代码:https://github.com/wyc192273/soul-learn-project/tree/main/sofa-demo搭建了简单的SpringCloud服务后,需要在项目中引入如下依赖:org.dromara</div>
</li>
<li><a href="/article/1892395273758502912.htm"
title="【2025年】全国CTF夺旗赛-从零基础入门到竞赛,看这一篇就稳了!" target="_blank">【2025年】全国CTF夺旗赛-从零基础入门到竞赛,看这一篇就稳了!</a>
<span class="text-muted">网安詹姆斯</span>
<a class="tag" taget="_blank" href="/search/web%E5%AE%89%E5%85%A8/1.htm">web安全</a><a class="tag" taget="_blank" href="/search/CTF/1.htm">CTF</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8%E5%A4%A7%E8%B5%9B/1.htm">网络安全大赛</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a>
<div>【2025年】全国CTF夺旗赛-从零基础入门到竞赛,看这一篇就稳了!基于入门网络安全/黑客打造的:黑客&网络安全入门&进阶学习资源包目录一、CTF简介二、CTF竞赛模式三、CTF各大题型简介四、CTF学习路线4.1、初期1、html+css+js(2-3天)2、apache+php(4-5天)3、mysql(2-3天)4、python(2-3天)5、burpsuite(1-2天)4.2、中期1、S</div>
</li>
<li><a href="/article/1892392376316522496.htm"
title="机器学习·文本数据读写处理" target="_blank">机器学习·文本数据读写处理</a>
<span class="text-muted">AAA顶置摸鱼</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86/1.htm">数据处理</a>
<div>前言在自然语言处理的第一步,需要面对的是各种各样以不同形式表现的文本数据,比如,txt、Excel中的表格数据,还有无法直接打开的pkl文件等。针对这些不同类型的数据,可以基于Python中的基本功能函数或者调用某些库进行读写以及作一些基本的处理。一、文本数据读写方法1.读写TXT文件读取方法:read():读取整个文件,返回字符串。readline():逐行读取,返回字符串。readlines(</div>
</li>
<li><a href="/article/1892392249963114496.htm"
title="LQB(4)-python-DFS搜索" target="_blank">LQB(4)-python-DFS搜索</a>
<span class="text-muted">AAA顶置摸鱼</span>
<a class="tag" taget="_blank" href="/search/%E8%93%9D%E6%A1%A5%E6%9D%AFpython%E7%BB%84/1.htm">蓝桥杯python组</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88/1.htm">深度优先</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E8%93%9D%E6%A1%A5%E6%9D%AF/1.htm">蓝桥杯</a>
<div>前言DFS即深度优先搜索(Depth-FirstSearch),是一种用于遍历或搜索树或图的算法,有三种核心的应用场景(基础遍历、回溯、剪枝)。一、DFS-基础遍历1.核心原理深度优先搜索(DFS)是一种遍历或搜索树/图的算法,优先沿着一条路径尽可能深入,直到无法继续再回溯。实现方式:递归:隐式利用系统调用栈。栈模拟:显式使用栈数据结构。2.代码实现(1)递归实现(树结构)classTreeNod</div>
</li>
<li><a href="/article/1892390738520502272.htm"
title="前端基础入门:HTML、CSS 和 JavaScript" target="_blank">前端基础入门:HTML、CSS 和 JavaScript</a>
<span class="text-muted">阿绵</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/js/1.htm">js</a>
<div>在现代网页开发中,前端技术扮演着至关重要的角色。无论是个人网站、企业官网,还是复杂的Web应用程序,前端开发的基础技术HTML、CSS和JavaScript都是每个开发者必须掌握的核心技能。本文将详细介绍这三者的基本概念及其应用一、HTML——网页的骨架HTML(HyperTextMarkupLanguage)是构建网页的基础语言。它是网页的结构和内容的标记语言,决定了网页上的文本、图像、表单等元</div>
</li>
<li><a href="/article/1892390108330520576.htm"
title="Python中LLM的知识图谱构建:动态更新与推理" target="_blank">Python中LLM的知识图谱构建:动态更新与推理</a>
<span class="text-muted">二进制独立开发</span>
<a class="tag" taget="_blank" href="/search/GenAI%E4%B8%8EPython/1.htm">GenAI与Python</a><a class="tag" taget="_blank" href="/search/%E9%9D%9E%E7%BA%AF%E7%B2%B9GenAI/1.htm">非纯粹GenAI</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E7%9F%A5%E8%AF%86%E5%9B%BE%E8%B0%B1/1.htm">知识图谱</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86/1.htm">自然语言处理</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%B8%83%E5%BC%8F/1.htm">分布式</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a>
<div>文章目录引言1.知识图谱的基本概念1.1知识图谱的定义1.2知识图谱的构建流程2.利用LLM进行知识抽取2.1实体识别2.2关系抽取2.3属性抽取3.知识融合3.1实体对齐3.2冲突消解4.知识存储5.知识推理5.1规则推理5.2基于LLM的推理6.动态更新6.1增量更新6.2实时更新7.结论引言随着人工智能技术的飞速发展,知识图谱(KnowledgeGraph,KG)作为一种结构化的知识表示方法</div>
</li>
<li><a href="/article/1892387966651789312.htm"
title="Python's SQLAlchemy and Object-Relational Mapping" target="_blank">Python's SQLAlchemy and Object-Relational Mapping</a>
<span class="text-muted">zhanglizhuo</span>
<a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a>
<div>Acommontaskwhenprogramminganywebserviceistheconstructionofasoliddatabasebackend.Inthepast,programmerswouldwriterawSQLstatements,passthemtothedatabaseengineandparsethereturnedresultsasanormalarrayofrec</div>
</li>
<li><a href="/article/1892387335333539840.htm"
title="Jira,一个强大灵活的项目和任务管理工具 Python 库" target="_blank">Jira,一个强大灵活的项目和任务管理工具 Python 库</a>
<span class="text-muted">图灵学者</span>
<a class="tag" taget="_blank" href="/search/python%E7%B2%BE%E5%8D%8E/1.htm">python精华</a><a class="tag" taget="_blank" href="/search/jira/1.htm">jira</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
<div>目录01初识Jira为什么选择Jira?02安装与配置安装jira库配置Jira访问获取APItoken:配置Python环境:03基本操作创建项目创建任务查询任务更新任务删除任务04高级操作处理子任务搜索任务添加附件评论任务05实战案例自动化创建与分配任务自动生成项目报告06结语01初识JiraJira是Atlassian公司开发的一款项目和任务管理工具。它广泛应用于软件开发、IT支持、营销等各</div>
</li>
<li><a href="/article/1892386579293466624.htm"
title="03.Docker 命令帮助" target="_blank">03.Docker 命令帮助</a>
<span class="text-muted">转身後 默落</span>
<a class="tag" taget="_blank" href="/search/Docker/1.htm">Docker</a><a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/eureka/1.htm">eureka</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a>
<div>Docker命令帮助Docker命令帮助1.docker命令帮助2.docker优化Docker命令帮助docker命令是最常使用的docker客户端命令,其后面可以加不同的参数以实现不同的功能。1.docker命令帮助官方文档:https://docs.docker.com/reference/cli/docker/docker[OPTIONS]COMMANDCOMMAND分为:Manageme</div>
</li>
<li><a href="/article/117.htm"
title="Algorithm" target="_blank">Algorithm</a>
<span class="text-muted">香水浓</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/Algorithm/1.htm">Algorithm</a>
<div>冒泡排序
public static void sort(Integer[] param) {
for (int i = param.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
int current = param[j];
int next = param[j + 1];</div>
</li>
<li><a href="/article/244.htm"
title="mongoDB 复杂查询表达式" target="_blank">mongoDB 复杂查询表达式</a>
<span class="text-muted">开窍的石头</span>
<a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a>
<div>1:count
Pg: db.user.find().count();
统计多少条数据
2:不等于$ne
Pg: db.user.find({_id:{$ne:3}},{name:1,sex:1,_id:0});
查询id不等于3的数据。
3:大于$gt $gte(大于等于)
&n</div>
</li>
<li><a href="/article/371.htm"
title="Jboss Java heap space异常解决方法, jboss OutOfMemoryError : PermGen space" target="_blank">Jboss Java heap space异常解决方法, jboss OutOfMemoryError : PermGen space</a>
<span class="text-muted">0624chenhong</span>
<a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</a><a class="tag" taget="_blank" href="/search/jboss/1.htm">jboss</a>
<div>转自
http://blog.csdn.net/zou274/article/details/5552630
解决办法:
window->preferences->java->installed jres->edit jre
把default vm arguments 的参数设为-Xms64m -Xmx512m
----------------</div>
</li>
<li><a href="/article/498.htm"
title="文件上传 下载 解析 相对路径" target="_blank">文件上传 下载 解析 相对路径</a>
<span class="text-muted">不懂事的小屁孩</span>
<a class="tag" taget="_blank" href="/search/%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0/1.htm">文件上传</a>
<div>有点坑吧,弄这么一个简单的东西弄了一天多,身边还有大神指导着,网上各种百度着。
下面总结一下遇到的问题:
文件上传,在页面上传的时候,不要想着去操作绝对路径,浏览器会对客户端的信息进行保护,避免用户信息收到攻击。
在上传图片,或者文件时,使用form表单来操作。
前台通过form表单传输一个流到后台,而不是ajax传递参数到后台,代码如下:
<form action=&</div>
</li>
<li><a href="/article/625.htm"
title="怎么实现qq空间批量点赞" target="_blank">怎么实现qq空间批量点赞</a>
<span class="text-muted">换个号韩国红果果</span>
<a class="tag" taget="_blank" href="/search/qq/1.htm">qq</a>
<div>纯粹为了好玩!!
逻辑很简单
1 打开浏览器console;输入以下代码。
先上添加赞的代码
var tools={};
//添加所有赞
function init(){
document.body.scrollTop=10000;
setTimeout(function(){document.body.scrollTop=0;},2000);//加</div>
</li>
<li><a href="/article/752.htm"
title="判断是否为中文" target="_blank">判断是否为中文</a>
<span class="text-muted">灵静志远</span>
<a class="tag" taget="_blank" href="/search/%E4%B8%AD%E6%96%87/1.htm">中文</a>
<div>方法一:
public class Zhidao {
public static void main(String args[]) {
String s = "sdf灭礌 kjl d{';\fdsjlk是";
int n=0;
for(int i=0; i<s.length(); i++) {
n = (int)s.charAt(i);
if((</div>
</li>
<li><a href="/article/879.htm"
title="一个电话面试后总结" target="_blank">一个电话面试后总结</a>
<span class="text-muted">a-john</span>
<a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a>
<div>今天,接了一个电话面试,对于还是初学者的我来说,紧张了半天。
面试的问题分了层次,对于一类问题,由简到难。自己觉得回答不好的地方作了一下总结:
在谈到集合类的时候,举几个常用的集合类,想都没想,直接说了list,map。
然后对list和map分别举几个类型:
list方面:ArrayList,LinkedList。在谈到他们的区别时,愣住了</div>
</li>
<li><a href="/article/1006.htm"
title="MSSQL中Escape转义的使用" target="_blank">MSSQL中Escape转义的使用</a>
<span class="text-muted">aijuans</span>
<a class="tag" taget="_blank" href="/search/MSSQL/1.htm">MSSQL</a>
<div>IF OBJECT_ID('tempdb..#ABC') is not null
drop table tempdb..#ABC
create table #ABC
(
PATHNAME NVARCHAR(50)
)
insert into #ABC
SELECT N'/ABCDEFGHI'
UNION ALL SELECT N'/ABCDGAFGASASSDFA'
UNION ALL</div>
</li>
<li><a href="/article/1133.htm"
title="一个简单的存储过程" target="_blank">一个简单的存储过程</a>
<span class="text-muted">asialee</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B/1.htm">存储过程</a><a class="tag" taget="_blank" href="/search/%E6%9E%84%E9%80%A0%E6%95%B0%E6%8D%AE/1.htm">构造数据</a><a class="tag" taget="_blank" href="/search/%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5/1.htm">批量插入</a>
<div> 今天要批量的生成一批测试数据,其中中间有部分数据是变化的,本来想写个程序来生成的,后来想到存储过程就可以搞定,所以随手写了一个,记录在此:
DELIMITER $$
DROP PROCEDURE IF EXISTS inse</div>
</li>
<li><a href="/article/1260.htm"
title="annot convert from HomeFragment_1 to Fragment" target="_blank">annot convert from HomeFragment_1 to Fragment</a>
<span class="text-muted">百合不是茶</span>
<a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/%E5%AF%BC%E5%8C%85%E9%94%99%E8%AF%AF/1.htm">导包错误</a>
<div>创建了几个类继承Fragment, 需要将创建的类存储在ArrayList<Fragment>中; 出现不能将new 出来的对象放到队列中,原因很简单;
创建类时引入包是:import android.app.Fragment;
创建队列和对象时使用的包是:import android.support.v4.ap</div>
</li>
<li><a href="/article/1387.htm"
title="Weblogic10两种修改端口的方法" target="_blank">Weblogic10两种修改端口的方法</a>
<span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/weblogic/1.htm">weblogic</a><a class="tag" taget="_blank" href="/search/%E7%AB%AF%E5%8F%A3%E5%8F%B7/1.htm">端口号</a><a class="tag" taget="_blank" href="/search/%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86/1.htm">配置管理</a><a class="tag" taget="_blank" href="/search/config.xml/1.htm">config.xml</a>
<div>一.进入控制台进行修改 1.进入控制台: http://127.0.0.1:7001/console 2.展开左边树菜单 域结构->环境->服务器-->点击AdminServer(管理) &</div>
</li>
<li><a href="/article/1514.htm"
title="mysql 操作指令" target="_blank">mysql 操作指令</a>
<span class="text-muted">征客丶</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
<div>一、连接mysql
进入 mysql 的安装目录;
$ bin/mysql -p [host IP 如果是登录本地的mysql 可以不写 -p 直接 -u] -u [userName] -p
输入密码,回车,接连;
二、权限操作[如果你很了解mysql数据库后,你可以直接去修改系统表,然后用 mysql> flush privileges; 指令让权限生效]
1、赋权
mys</div>
</li>
<li><a href="/article/1641.htm"
title="【Hive一】Hive入门" target="_blank">【Hive一】Hive入门</a>
<span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/hive/1.htm">hive</a>
<div>Hive安装与配置
Hive的运行需要依赖于Hadoop,因此需要首先安装Hadoop2.5.2,并且Hive的启动前需要首先启动Hadoop。
Hive安装和配置的步骤
1. 从如下地址下载Hive0.14.0
http://mirror.bit.edu.cn/apache/hive/
2.解压hive,在系统变</div>
</li>
<li><a href="/article/1768.htm"
title="ajax 三种提交请求的方法" target="_blank">ajax 三种提交请求的方法</a>
<span class="text-muted">BlueSkator</span>
<a class="tag" taget="_blank" href="/search/Ajax/1.htm">Ajax</a><a class="tag" taget="_blank" href="/search/jqery/1.htm">jqery</a>
<div>1、ajax 提交请求
$.ajax({
type:"post",
url : "${ctx}/front/Hotel/getAllHotelByAjax.do",
dataType : "json",
success : function(result) {
try {
for(v</div>
</li>
<li><a href="/article/1895.htm"
title="mongodb开发环境下的搭建入门" target="_blank">mongodb开发环境下的搭建入门</a>
<span class="text-muted">braveCS</span>
<a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a>
<div>
linux下安装mongodb
1)官网下载mongodb-linux-x86_64-rhel62-3.0.4.gz
2)linux 解压
gzip -d mongodb-linux-x86_64-rhel62-3.0.4.gz;
mv mongodb-linux-x86_64-rhel62-3.0.4 mongodb-linux-x86_64-rhel62-</div>
</li>
<li><a href="/article/2022.htm"
title="编程之美-最短摘要的生成" target="_blank">编程之美-最短摘要的生成</a>
<span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B%E4%B9%8B%E7%BE%8E/1.htm">编程之美</a>
<div>
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class ShortestAbstract {
/**
* 编程之美 最短摘要的生成
* 扫描过程始终保持一个[pBegin,pEnd]的range,初始化确保[pBegin,pEnd]的ran</div>
</li>
<li><a href="/article/2149.htm"
title="json数据解析及typeof" target="_blank">json数据解析及typeof</a>
<span class="text-muted">chengxuyuancsdn</span>
<a class="tag" taget="_blank" href="/search/js/1.htm">js</a><a class="tag" taget="_blank" href="/search/typeof/1.htm">typeof</a><a class="tag" taget="_blank" href="/search/json%E8%A7%A3%E6%9E%90/1.htm">json解析</a>
<div>
// json格式
var people='{"authors": [{"firstName": "AAA","lastName": "BBB"},'
+' {"firstName": "CCC&</div>
</li>
<li><a href="/article/2276.htm"
title="流程系统设计的层次和目标" target="_blank">流程系统设计的层次和目标</a>
<span class="text-muted">comsci</span>
<a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a><a class="tag" taget="_blank" href="/search/%E8%84%9A%E6%9C%AC/1.htm">脚本</a>
<div>
流程系统设计的层次和目标
</div>
</li>
<li><a href="/article/2403.htm"
title="RMAN List和report 命令" target="_blank">RMAN List和report 命令</a>
<span class="text-muted">daizj</span>
<a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/list/1.htm">list</a><a class="tag" taget="_blank" href="/search/report/1.htm">report</a><a class="tag" taget="_blank" href="/search/rman/1.htm">rman</a>
<div>LIST 命令
使用RMAN LIST 命令显示有关资料档案库中记录的备份集、代理副本和映像副本的
信息。使用此命令可列出:
• RMAN 资料档案库中状态不是AVAILABLE 的备份和副本
• 可用的且可以用于还原操作的数据文件备份和副本
• 备份集和副本,其中包含指定数据文件列表或指定表空间的备份
• 包含指定名称或范围的所有归档日志备份的备份集和副本
• 由标记、完成时间、可</div>
</li>
<li><a href="/article/2530.htm"
title="二叉树:红黑树" target="_blank">二叉树:红黑树</a>
<span class="text-muted">dieslrae</span>
<a class="tag" taget="_blank" href="/search/%E4%BA%8C%E5%8F%89%E6%A0%91/1.htm">二叉树</a>
<div> 红黑树是一种自平衡的二叉树,它的查找,插入,删除操作时间复杂度皆为O(logN),不会出现普通二叉搜索树在最差情况时时间复杂度会变为O(N)的问题.
红黑树必须遵循红黑规则,规则如下
1、每个节点不是红就是黑。 2、根总是黑的 &</div>
</li>
<li><a href="/article/2657.htm"
title="C语言homework3,7个小题目的代码" target="_blank">C语言homework3,7个小题目的代码</a>
<span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/c/1.htm">c</a>
<div>1、打印100以内的所有奇数。
# include <stdio.h>
int main(void)
{
int i;
for (i=1; i<=100; i++)
{
if (i%2 != 0)
printf("%d ", i);
}
return 0;
}
2、从键盘上输入10个整数,</div>
</li>
<li><a href="/article/2784.htm"
title="自定义按钮, 图片在上, 文字在下, 居中显示" target="_blank">自定义按钮, 图片在上, 文字在下, 居中显示</a>
<span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/%E8%87%AA%E5%AE%9A%E4%B9%89/1.htm">自定义</a>
<div>#import <UIKit/UIKit.h>
@interface MyButton : UIButton
-(void)setFrame:(CGRect)frame ImageName:(NSString*)imageName Target:(id)target Action:(SEL)action Title:(NSString*)title Font:(CGFloa</div>
</li>
<li><a href="/article/2911.htm"
title="MySQL查询语句练习题,测试足够用了" target="_blank">MySQL查询语句练习题,测试足够用了</a>
<span class="text-muted">flyvszhb</span>
<a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
<div>http://blog.sina.com.cn/s/blog_767d65530101861c.html
1.创建student和score表
CREATE TABLE student (
id INT(10) NOT NULL UNIQUE PRIMARY KEY ,
name VARCHAR</div>
</li>
<li><a href="/article/3038.htm"
title="转:MyBatis Generator 详解" target="_blank">转:MyBatis Generator 详解</a>
<span class="text-muted">happyqing</span>
<a class="tag" taget="_blank" href="/search/mybatis/1.htm">mybatis</a>
<div>
MyBatis Generator 详解
http://blog.csdn.net/isea533/article/details/42102297
MyBatis Generator详解
http://git.oschina.net/free/Mybatis_Utils/blob/master/MybatisGeneator/MybatisGeneator.</div>
</li>
<li><a href="/article/3165.htm"
title="让程序员少走弯路的14个忠告" target="_blank">让程序员少走弯路的14个忠告</a>
<span class="text-muted">jingjing0907</span>
<a class="tag" taget="_blank" href="/search/%E5%B7%A5%E4%BD%9C/1.htm">工作</a><a class="tag" taget="_blank" href="/search/%E8%AE%A1%E5%88%92/1.htm">计划</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a>
<div>
无论是谁,在刚进入某个领域之时,有再大的雄心壮志也敌不过眼前的迷茫:不知道应该怎么做,不知道应该做什么。下面是一名软件开发人员所学到的经验,希望能对大家有所帮助
1.不要害怕在工作中学习。
只要有电脑,就可以通过电子阅读器阅读报纸和大多数书籍。如果你只是做好自己的本职工作以及分配的任务,那是学不到很多东西的。如果你盲目地要求更多的工作,也是不可能提升自己的。放</div>
</li>
<li><a href="/article/3292.htm"
title="nginx和NetScaler区别" target="_blank">nginx和NetScaler区别</a>
<span class="text-muted">流浪鱼</span>
<a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a>
<div>NetScaler是一个完整的包含操作系统和应用交付功能的产品,Nginx并不包含操作系统,在处理连接方面,需要依赖于操作系统,所以在并发连接数方面和防DoS攻击方面,Nginx不具备优势。
2.易用性方面差别也比较大。Nginx对管理员的水平要求比较高,参数比较多,不确定性给运营带来隐患。在NetScaler常见的配置如健康检查,HA等,在Nginx上的配置的实现相对复杂。
3.策略灵活度方</div>
</li>
<li><a href="/article/3419.htm"
title="第11章 动画效果(下)" target="_blank">第11章 动画效果(下)</a>
<span class="text-muted">onestopweb</span>
<a class="tag" taget="_blank" href="/search/%E5%8A%A8%E7%94%BB/1.htm">动画</a>
<div>index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/</div>
</li>
<li><a href="/article/3546.htm"
title="FAQ - SAP BW BO roadmap" target="_blank">FAQ - SAP BW BO roadmap</a>
<span class="text-muted">blueoxygen</span>
<a class="tag" taget="_blank" href="/search/BO/1.htm">BO</a><a class="tag" taget="_blank" href="/search/BW/1.htm">BW</a>
<div>http://www.sdn.sap.com/irj/boc/business-objects-for-sap-faq
Besides, I care that how to integrate tightly.
By the way, for BW consultants, please just focus on Query Designer which i</div>
</li>
<li><a href="/article/3673.htm"
title="关于java堆内存溢出的几种情况" target="_blank">关于java堆内存溢出的几种情况</a>
<span class="text-muted">tomcat_oracle</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</a><a class="tag" taget="_blank" href="/search/jdk/1.htm">jdk</a><a class="tag" taget="_blank" href="/search/thread/1.htm">thread</a>
<div>【情况一】:
java.lang.OutOfMemoryError: Java heap space:这种是java堆内存不够,一个原因是真不够,另一个原因是程序中有死循环; 如果是java堆内存不够的话,可以通过调整JVM下面的配置来解决: <jvm-arg>-Xms3062m</jvm-arg> <jvm-arg>-Xmx</div>
</li>
<li><a href="/article/3800.htm"
title="Manifest.permission_group权限组" target="_blank">Manifest.permission_group权限组</a>
<span class="text-muted">阿尔萨斯</span>
<a class="tag" taget="_blank" href="/search/Permission/1.htm">Permission</a>
<div>结构
继承关系
public static final class Manifest.permission_group extends Object
java.lang.Object
android. Manifest.permission_group 常量
ACCOUNTS 直接通过统计管理器访问管理的统计
COST_MONEY可以用来让用户花钱但不需要通过与他们直接牵涉的权限
D</div>
</li>
</ul>
</div>
</div>
</div>
<div>
<div class="container">
<div class="indexes">
<strong>按字母分类:</strong>
<a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
</div>
</div>
</div>
<footer id="footer" class="mb30 mt30">
<div class="container">
<div class="footBglm">
<a target="_blank" href="/">首页</a> -
<a target="_blank" href="/custom/about.htm">关于我们</a> -
<a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
<a target="_blank" href="/sitemap.txt">Sitemap</a> -
<a target="_blank" href="/custom/delete.htm">侵权投诉</a>
</div>
<div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
<!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
</div>
</div>
</footer>
<!-- 代码高亮 -->
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
<link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
<script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>
</body>
</html>