【Web Crawler】Python 的 urllib.request 用于 HTTP 请求

如果您需要使用 Python 发出 HTTP 请求,那么您可能会发现自己被引导至 brilliantrequests库。尽管它是一个很棒的库,但您可能已经注意到它并不是 Python 的内置部分。如果您出于某种原因更喜欢限制依赖项并坚持使用标准库 Python,那么您可以使用urllib.request!

在本教程中,您将:

  • 了解如何发出基本的HTTP 请求urllib.request

  • 深入了解HTTP 消息的具体细节及其urllib.request表示方式

  • 了解如何处理HTTP 消息的字符编码

  • 探索使用时的一些常见错误urllib.request并学习如何解决它们

  • 将您的脚趾浸入经过身份验证的请求的世界urllib.request

  • 理解为什么两者urllib和requests库都存在以及何时使用其中一个或另一个

如果您听说过 HTTP 请求,包括GETPOST,那么您可能已经准备好学习本教程了。此外,您应该已经使用 Python读取和写入文件,最好使用上下文管理器,至少一次。

最终,您会发现提出请求不一定是令人沮丧的经历,尽管它确实有这样的名声。您经常遇到的许多问题都是由于 Internet 这个奇妙事物的内在复杂性造成的。好消息是该urllib.request模块可以帮助揭开这种复杂性的神秘面纱。

了解更多信息: 单击此处与 290,000 多名 Python 开发人员一起阅读 Real Python Newsletter ,获取新的 Python 教程和新闻,让您成为更高效的 Pythonista。

基本 HTTP GET 请求urllib.request

在深入了解什么是 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处理它们。这种理解将为解决许多不同类型的问题提供坚实的基础。

HTTP 消息的具体细节

要了解您在使用 时可能遇到的一些问题,您urllib.request需要检查响应是如何由 表示的urllib.request。为此,您将受益于对HTTP 消息是什么的高级概述,这就是您将在本节中获得的内容。

在进行高级概述之前,先简要说明一下参考来源。如果您想深入了解技术领域,互联网工程任务组 (IETF)有大量的征求意见 (RFC)文档。这些文档最终成为 HTTP 消息之类的实际规范。例如, RFC 7230,第 1 部分:消息语法和路由都是关于 HTTP 消息的。

如果您正在寻找比 RFC 更容易理解的参考资料,那么Mozilla 开发者网络 (MDN)有大量参考文章。例如,他们关于HTTP 消息的文章虽然仍然是技术性的,但更容易理解。

现在您已经了解了这些基本的参考信息来源,在下一节中您将对 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.requestHTTPResponse对象。urllib.request模块本身依赖于低级http模块,您不需要直接与之交互。不过,您确实最终会使用一些提供的数据结构http,例如HTTPResponseHTTPMessage

注意:在 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(),从而阻止正确的拆解。为了使这个调用成为无条件的,就像它应该的那样,你可以使用带有一个和一个子句的tryexcept块: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/1903873252669845504.htm"
                           title="基于Python PYQT5 的相机定时采集图像程序,GUI打包独立运行" target="_blank">基于Python PYQT5 的相机定时采集图像程序,GUI打包独立运行</a>
                        <span class="text-muted">夏时summer time</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/qt/1.htm">qt</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E7%A0%81%E7%9B%B8%E6%9C%BA/1.htm">数码相机</a><a class="tag" taget="_blank" href="/search/%E7%9B%B8%E6%9C%BA/1.htm">相机</a>
                        <div>基于PythonPYQT5编写相机定时采集图像及手动采集版本介绍Python3.6pyqt55.15.4pyqt5-tools5.15.4.3.2另外就是常用的cv2和numpy包fromPyQt5importQtCore,QtGui,QtWidgetsfromPyQt5importQtCore,QtGui,QtWidgetsimportcv2importnumpyasnpfromdatetime</div>
                    </li>
                    <li><a href="/article/1903871489321529344.htm"
                           title="《AI医疗系统开发实战录》第6期——智能导诊系统实战" target="_blank">《AI医疗系统开发实战录》第6期——智能导诊系统实战</a>
                        <span class="text-muted">骆驼_代码狂魔</span>
<a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98%E7%9A%84%E6%B3%95%E5%AE%9D/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/django/1.htm">django</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/neo4j/1.htm">neo4j</a><a class="tag" taget="_blank" href="/search/%E7%9F%A5%E8%AF%86%E5%9B%BE%E8%B0%B1/1.htm">知识图谱</a>
                        <div>关注我,后期文章全部免费开放,一起推进AI医疗的发展核心主题:如何构建95%准确率的智能导诊系统?技术突破:结合BERT+知识图谱的混合模型设计一、智能导诊架构设计python基于BERT的意图识别模型(PyTorch)fromtransformersimportBertTokenizer,BertForSequenceClassificationimporttorchclassTriageMod</div>
                    </li>
                    <li><a href="/article/1903870352891637760.htm"
                           title="基于Qt开发:实现对海康威视网络摄像头视频画面实时预览" target="_blank">基于Qt开发:实现对海康威视网络摄像头视频画面实时预览</a>
                        <span class="text-muted">鱼弦</span>
<a class="tag" taget="_blank" href="/search/Qt%E5%AD%A6%E4%B9%A0%E4%B8%8E%E5%AE%9E%E8%B7%B5/1.htm">Qt学习与实践</a><a class="tag" taget="_blank" href="/search/%E9%9F%B3%E8%A7%86%E9%A2%91%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E5%AE%9E%E8%B7%B5/1.htm">音视频开发系列实践</a><a class="tag" taget="_blank" href="/search/Linux%E7%B3%BB%E7%BB%9F%E7%BC%96%E7%A8%8B%E4%B8%8E%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/1.htm">Linux系统编程与驱动开发</a><a class="tag" taget="_blank" href="/search/arm%E5%BC%80%E5%8F%91/1.htm">arm开发</a>
                        <div>鱼弦:公众号【红尘灯塔】,CSDN博客专家、内容合伙人、新星导师、全栈领域优质创作者、51CTO(Top红人+专家博主)、github开源爱好者(go-zero源码二次开发、游戏后端架构https://github.com/Peakchen)介绍:本文将介绍如何基于Qt开发框架,实现对海康威视网络摄像头的二次开发应用程序。该应用程序可以实时预览摄像头视频画面,并支持控制云台的水平和垂直移动。这种二</div>
                    </li>
                    <li><a href="/article/1903866571588169728.htm"
                           title="C++在线OJ负载均衡项目" target="_blank">C++在线OJ负载均衡项目</a>
                        <span class="text-muted">平凡的小y</span>
<a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>1.演示项目项目源码链接:2.项目所用技术和开发环境所用技术C++STL标准库Boost准标准库(字符串切割)cpp-httplib第三方开源网络库ctemplate第三方开源前端网页渲染库jsoncpp第三方开源序列化、反序列化库负载均衡设计MySQLCconnectAce前端在线编辑器html/css/js/jquery/ajax开发环境Ubuntu云服务器vscodeMysqlWorkben</div>
                    </li>
                    <li><a href="/article/1903865186255695872.htm"
                           title="量化交易系统中如何处理机器学习模型的训练和部署?" target="_blank">量化交易系统中如何处理机器学习模型的训练和部署?</a>
                        <span class="text-muted">openwin_top</span>
<a class="tag" taget="_blank" href="/search/%E9%87%8F%E5%8C%96%E4%BA%A4%E6%98%93%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91/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/%E9%87%8F%E5%8C%96%E4%BA%A4%E6%98%93/1.htm">量化交易</a>
                        <div>microPythonPython最小内核源码解析NI-motion运动控制c语言示例代码解析python编程示例系列python编程示例系列二python的Web神器Streamlit如何应聘高薪职位量化交易系统中,机器学习模型的训练和部署需要遵循一套严密的流程,以确保模型的可靠性、性能和安全性。以下是详细描述以及相关的示例:1.数据收集和预处理数据收集在量化交易中,数据是最重要的资产。收集的数</div>
                    </li>
                    <li><a href="/article/1903864806478245888.htm"
                           title="Mac下载python并安装" target="_blank">Mac下载python并安装</a>
                        <span class="text-muted">小小酥*</span>

                        <div>下载pythonPython官网:https://www.python.org/进入官网后点击download,选择MacOSX版本2.安装MAC系统一般都自带有Python2.x版本的环境,你也可以在链接https://www.python.org/downloads/mac-osx/上下载最新版安装。3.设置环境变量程序和可执行文件可以在许多目录,而这些路径很可能不在操作系统提供可执行文件的搜</div>
                    </li>
                    <li><a href="/article/1903864808059498496.htm"
                           title="Python使用minIO上传下载" target="_blank">Python使用minIO上传下载</a>
                        <span class="text-muted">身似山河挺脊梁</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a>
                        <div>前提VSCode+Python3.9minIO有Python的例子1.python生成临时文件2.写入一些数据3.上传到minIO4.获取分享出连接5.发出通知#创建一个客户端minioClient=Minio(endpoint='xx',access_key='xx',secret_key='xx',secure=False)#生成文件名current_datetime=datetime.dat</div>
                    </li>
                    <li><a href="/article/1903864680124837888.htm"
                           title="深入理解Python上下文管理器" target="_blank">深入理解Python上下文管理器</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/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>1.什么是上下文管理器?2.with语句的魔法3.创建上下文管理器的两种方式3.1基于类的实现3.2使用contextlib模块4.异常处理1.什么是上下文管理器?上下文管理器(ContextManager)是Python中用于精确分配和释放资源的机制。它通过__enter__()和__exit__()两个魔术方法实现了上下文管理协议,确保即使在代码执行出错的情况下,资源也能被正确清理。#经典文件</div>
                    </li>
                    <li><a href="/article/1903864428059750400.htm"
                           title="【Appium】Appium征服安卓自动化:GitHub 10.5k+星开源神器,Python代码实战全解析!" target="_blank">【Appium】Appium征服安卓自动化:GitHub 10.5k+星开源神器,Python代码实战全解析!</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/%E6%B5%8B%E8%AF%95/1.htm">测试</a><a class="tag" taget="_blank" href="/search/appium/1.htm">appium</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E5%8A%A8%E5%8C%96/1.htm">自动化</a>
                        <div>Appium一、为什么开发者都在用Appium?二、环境搭建:5分钟极速配置2.1核心工具链2.2安卓设备连接三、脚本实战:从零编写自动化操作3.1示例1:自动登录微信并发送消息3.2示例2:动态滑动屏幕与数据抓取四、避坑指南4.1元素定位优化4.2稳定性增强4.3云真机集成五、生态扩展:超越安卓的自动化版图一、为什么开发者都在用Appium?万星认证:GitHub超10.5k+星标,活跃社区持续</div>
                    </li>
                    <li><a href="/article/1903863672028065792.htm"
                           title="基于Streamlit实现的音频处理示例" target="_blank">基于Streamlit实现的音频处理示例</a>
                        <span class="text-muted">大霸王龙</span>
<a class="tag" taget="_blank" href="/search/%E9%9F%B3%E8%A7%86%E9%A2%91/1.htm">音视频</a><a class="tag" taget="_blank" href="/search/ffmpeg/1.htm">ffmpeg</a>
                        <div>基于Streamlit实现的音频处理示例,包含录音、语音转文本、文件下载和进度显示功能,整合了多个技术方案:一、环境准备#安装依赖库pipinstallstreamlitstreamlit-webrtcaudio-recorder-streamlitopenai-whisperpython-dotx二、完整示例代码importstreamlitasstfromaudio_recorder_stre</div>
                    </li>
                    <li><a href="/article/1903861275209822208.htm"
                           title="npm install 报错 gyp info it worked if it ends with ok npm ERR gyp verb cli [" target="_blank">npm install 报错 gyp info it worked if it ends with ok npm ERR gyp verb cli [</a>
                        <span class="text-muted">m0_61083409</span>
<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/npm/1.htm">npm</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a>
                        <div>今天新启动一个项目,在npminstall安装依赖项时出现报错。ERR!code1npmERR!pathC:UsersAdministratorDesktope31mall-admin-webode_modulesode-sassnpmERR!commandfailednpmERR!commandC:Windowssystem32cmd.exe/d/s/cnodescripts/build.jsn</div>
                    </li>
                    <li><a href="/article/1903861274085748736.htm"
                           title="npm错误 gyp错误 vs版本不对 msvs_version不兼容" target="_blank">npm错误 gyp错误 vs版本不对 msvs_version不兼容</a>
                        <span class="text-muted">澎湖Java架构师</span>
<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/npm/1.htm">npm</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>npm错误gyp错误vs版本不对msvs_version不兼容windowsSDK报错执行更新GYP语句第一种方案第二种方案执行更新GYP语句npminstall-gnode-gyp最新的GYP好像已经不支持Python2.7版本,npm会提示你更新都3.*.*版本安装Node.js的时候一定要勾选以下这个,会自动检测安装缺少的环境第一种方案管理员运行CMD(PowerShell也行)执行更新工具</div>
                    </li>
                    <li><a href="/article/1903860767069892608.htm"
                           title="深入了解 ArangoDB 的图数据库应用与 Python 实践" target="_blank">深入了解 ArangoDB 的图数据库应用与 Python 实践</a>
                        <span class="text-muted">eahba</span>
<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/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>在当前数据驱动的时代,对连接数据的高效处理和分析需求日益增长。ArangoDB作为一个可扩展的图数据库系统,能够加速从连接数据中获取价值。本文将介绍如何使用Python连接和操作ArangoDB,并展示如何结合图问答链来获取数据洞察。技术背景介绍ArangoDB是一个多模型数据库,支持文档、图和键值类型的数据存储。其强大的图形存储和查询能力使其成为处理复杂数据关系的理想选择。通过JSON支持和单一</div>
                    </li>
                    <li><a href="/article/1903860514971250688.htm"
                           title="不懂英语可以学编程吗?,不懂英文可以学编程吗" target="_blank">不懂英语可以学编程吗?,不懂英文可以学编程吗</a>
                        <span class="text-muted">P5688346</span>
<a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a>
                        <div>大家好,给大家分享一下英语不好能学python编程吗,很多人还不知道这一点。下面详细解释一下。现在让我们来看看!Sourcecodedownload:本文相关源码提到人工智能,就不得不提Python编程语言,大多数人觉得编程语言肯定会涉及到很多代码,满屏的英文字母,想想就头疼,觉得自己不会英语,肯定学不好Python,但是不会英语到底能不能够学习Python呢,下面小编给大家分析分析。其实各位想要</div>
                    </li>
                    <li><a href="/article/1903859884932263936.htm"
                           title="android视频缓存框架 [AndroidVideoCache](https://github.com/danikula/AndroidVideoCache) 源码解析与评估" target="_blank">android视频缓存框架 [AndroidVideoCache](https://github.com/danikula/AndroidVideoCache) 源码解析与评估</a>
                        <span class="text-muted">MrJarvisDong</span>
<a class="tag" taget="_blank" href="/search/third/1.htm">third</a><a class="tag" taget="_blank" href="/search/party/1.htm">party</a><a class="tag" taget="_blank" href="/search/%E6%BA%90%E7%A0%81/1.htm">源码</a>
                        <div>文章目录android视频缓存框架[AndroidVideoCache](https://github.com/danikula/AndroidVideoCache)源码解析与评估引言使用方式关键类解析HttpProxyCacheServer代理缓存服务类**java.net.ProxySelector**代理选择Pinger判断本地serverSocket是否存活GetRequest封装用于获取</div>
                    </li>
                    <li><a href="/article/1903859758562078720.htm"
                           title="一、Python入门基础" target="_blank">一、Python入门基础</a>
                        <span class="text-muted">MeyrlNotFound</span>
<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>1.Python简介与环境搭建•了解Python的历史、特点和应用领域Python的历史Python是一种高级编程语言,由GuidovanRossum于1989年发明。Python语言的设计目标是让代码易读、易写、易维护,从而提高开发效率和代码质量。自其诞生以来,Python已从一个简单的系统管理工具发展成为一种广泛应用于多个领域的编程语言。Python的特点1.简单易学:Python的语法简洁明</div>
                    </li>
                    <li><a href="/article/1903858120061415424.htm"
                           title="npm error gyp info" target="_blank">npm error gyp info</a>
                        <span class="text-muted">计算机辅助工程</span>
<a class="tag" taget="_blank" href="/search/npm/1.htm">npm</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a>
                        <div>在使用npm安装Node.js包时,可能会遇到各种错误,其中gyp错误是比较常见的一种。gyp是Node.js的一个工具,用于编译C++代码。这些错误通常发生在需要编译原生模块的npm包时。下面是一些常见的原因和解决方法:常见原因及解决方法Python未安装或版本不兼容:Node.js使用Python来运行gyp。确保你的系统上安装了Python,并且版本与node-gyp兼容。通常推荐使用Pyt</div>
                    </li>
                    <li><a href="/article/1903857867765641216.htm"
                           title="计算机网络&性能优化相关内容详解" target="_blank">计算机网络&性能优化相关内容详解</a>
                        <span class="text-muted">GISer_Jinger</span>
<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>1.优化页面性能:根据搜索结果,优化可以从资源加载、渲染优化、缓存策略等方面入手。网页1提到合并文件、压缩图片、使用CDN和HTTP/2。网页2和3强调了关键资源划分、减少HTTP请求、代码拆分和预加载。我需要综合这些点,分块回答。2.滚动性能优化及虚拟滚动核心:用户提到虚拟滚动是关键。网页6、8、9、10详细介绍了虚拟滚动的原理,即仅渲染可视区域元素,减少DOM操作。需要总结这些内容,并指出核心</div>
                    </li>
                    <li><a href="/article/1903857615067213824.htm"
                           title="股票量化交易开发 Yfinance" target="_blank">股票量化交易开发 Yfinance</a>
                        <span class="text-muted">数字化转型2025</span>
<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>以下是一段基于Python的股票量化分析代码,包含数据获取、技术指标计算、策略回测和可视化功能:pythonimportyfinanceasyfimportpandasaspdimportnumpyasnpimportmatplotlib.pyplotaspltimportseabornassnsfrombacktestingimportBacktest,Strategyfrombacktesti</div>
                    </li>
                    <li><a href="/article/1903855978508513280.htm"
                           title="如何实现具备自动重连与心跳检测的WebSocket客户端" target="_blank">如何实现具备自动重连与心跳检测的WebSocket客户端</a>
                        <span class="text-muted">FFF-X</span>
<a class="tag" taget="_blank" href="/search/websocket/1.htm">websocket</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE/1.htm">网络协议</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a>
                        <div>本文介绍如何通过原生WebSocketAPI封装一个具备自动重连、心跳检测、错误恢复等能力的稳健客户端。适用于需要长连接的实时通讯场景(如聊天室、实时数据监控等)。核心功能亮点自动重连机制-指数退避策略重连心跳保活-双向检测连接活性消息可靠性-失败消息自动重发异常处理-错误分类处理机制状态管理-精准控制连接生命周期关键优化点说明事件监听优化改用addEventListener替代onopen等属性</div>
                    </li>
                    <li><a href="/article/1903854968197148672.htm"
                           title="人民日报报道,华为云赋能智能制造助力图扑软件构造数字孪生场景" target="_blank">人民日报报道,华为云赋能智能制造助力图扑软件构造数字孪生场景</a>
                        <span class="text-muted">智慧园区</span>
<a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BA/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/%E7%89%A9%E8%81%94%E7%BD%91/1.htm">物联网</a>
                        <div>2021年12月22日,《人民日报》头版头条刊登了《华为云赋能智能制造,助力图扑软件构造数字孪生场景》一文,聚焦数据可视化建设发展。报道指出,数字经济发展的背后,是大数据时趋势下各地区积极贯彻国家数字经济发展战略的时代精神;高效便捷管控的背后,是云端平台各大企业的互助共赢;高质精准2D、3D数据可视图的背后,是专注于数据可视化Web组态开发的厦门图扑软件科技有限公司。并对厦门图扑软件科技有限公司进</div>
                    </li>
                    <li><a href="/article/1903854460124327936.htm"
                           title="uni-app的滚动加载 uni-load-more组件使用" target="_blank">uni-app的滚动加载 uni-load-more组件使用</a>
                        <span class="text-muted">weixin_42885875</span>

                        <div>手机端的滚动加载其实就是PC端的分页,触底之后页数加一调用接口,将返回的数据连接在原来的数据后面,就大致完成了。使用组件https://ext.dcloud.net.cn/plugin?id=29exportdefault{data(){return{ifBottomRefresh:false,loadmore:'more',contentText:{"contentdown":"加载更多数据",</div>
                    </li>
                    <li><a href="/article/1903852445105188864.htm"
                           title="sqlmap笔记" target="_blank">sqlmap笔记</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-%E6%B8%97%E9%80%8F%E7%AC%94%E8%AE%B0/1.htm">网络安全-渗透笔记</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a>
                        <div>1.运行环境sqlmap是用Python编写的,因此首先需要确保你的系统上安装了Python。sqlmap支持Python2.6、2.7和Python3.4及以上版本。2.常用命令通用格式:bythonsqlmap.py-r注入点地址--参数-rpost请求-uget请求--level=测试等级--risk=测试风险-v显示详细信息级别-p针对某个注入点注入-threads更改线程数,加速--ba</div>
                    </li>
                    <li><a href="/article/1903851813753384960.htm"
                           title="计算机网络课程内容详解-ChatGPT4o作答" target="_blank">计算机网络课程内容详解-ChatGPT4o作答</a>
                        <span class="text-muted">部分分式</span>
<a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/1.htm">计算机网络</a>
                        <div>计算机网络课程是一门系统讲解网络体系结构、通信协议、网络技术和应用的专业课程,旨在帮助学生理解计算机网络的工作原理、设计思想和实际应用。以下是计算机网络课程内容的详细介绍,涵盖知识结构、主要内容及应用方向。一、课程目标掌握计算机网络的基本概念、结构及运行原理。理解计算机网络分层模型(如OSI七层模型和TCP/IP四层模型)。掌握常见的通信协议及其功能(如HTTP、FTP、DNS等)。学会网络设备(</div>
                    </li>
                    <li><a href="/article/1903850677071835136.htm"
                           title="通过浏览器扩展获取本机 MAC 地址" target="_blank">通过浏览器扩展获取本机 MAC 地址</a>
                        <span class="text-muted">云水木石</span>
<a class="tag" taget="_blank" href="/search/macos/1.htm">macos</a>
                        <div>在Web技术主导的B/S架构项目中,获取终端设备硬件信息(如MAC地址)的需求经常会碰到。尽管Electron/CEF等混合应用框架可通过系统级API轻松实现,但纯浏览器环境下的硬件信息获取则不那么容易。因为现代浏览器基于沙箱机制和隐私保护策略,严格禁止网页直接访问底层硬件资源。但用户的需求不能不考虑,特别是在做商业项目时,这时就不得不给出方案,总结下来有如下三种方案:扩展JSAPI:比如以前在做</div>
                    </li>
                    <li><a href="/article/1903849164857470976.htm"
                           title="python环境部署工具 uv" target="_blank">python环境部署工具 uv</a>
                        <span class="text-muted">Honnnnnn</span>
<a class="tag" taget="_blank" href="/search/uv/1.htm">uv</a>
                        <div>以原先使用的pipenv工具为例子,通过pipfile.lock生成requirements文件,再将requirements转成pyproject.toml文件,最后生成uv.lock基于当前虚拟环境导出requirements.txt--pipfreeze>requirements.txt(如果原先不是env而是基础的通过requirements.txt文件,省去转化requirements的</div>
                    </li>
                    <li><a href="/article/1903847273729683456.htm"
                           title="使用uni-app的组件(基础组件和扩展组件)" target="_blank">使用uni-app的组件(基础组件和扩展组件)</a>
                        <span class="text-muted">云海洋和天</span>
<a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a><a class="tag" taget="_blank" href="/search/%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">小程序</a><a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a><a class="tag" taget="_blank" href="/search/%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">小程序</a>
                        <div>目录一、使用基础组件二、使用扩展组件(uni-ui)方式一:npm安装方式二:通过uni-modules导入全部组件一、使用基础组件文档uni-app官网•组件•组件概述https://uniapp.dcloud.net.cn/component/基础组件在uni-app框架中已经内置,可以直接使用。示例如:使用内置组件icon二、使用扩展组件(uni-ui)文档</div>
                    </li>
                    <li><a href="/article/1903846137262043136.htm"
                           title="vLLM - 查看模型是否支持" target="_blank">vLLM - 查看模型是否支持</a>
                        <span class="text-muted">云客Coder</span>
<a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a>
                        <div>支持的模型:https://docs.vllm.ai/en/latest/models/supported_models.html要确定是否支持给定模型,您可以检查HF存储库中的config.json文件。如果"architectures"字段包含下面列出的模型架构,那么理论上应该支持它。查看模型架构查看模型的config.json中的architecturescat~/.cache/huggin</div>
                    </li>
                    <li><a href="/article/1903844751103291392.htm"
                           title="leetcode-hot100-python-专题三:滑动窗口" target="_blank">leetcode-hot100-python-专题三:滑动窗口</a>
                        <span class="text-muted">༺ Dorothy ༻</span>
<a class="tag" taget="_blank" href="/search/leetcode/1.htm">leetcode</a><a class="tag" taget="_blank" href="/search/hot100/1.htm">hot100</a><a class="tag" taget="_blank" href="/search/leetcode/1.htm">leetcode</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a>
                        <div>1、无重复字符的最长子串中等给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。示例1:输入:s=“abcabcbb”输出:3解释:因为无重复字符的最长子串是“abc”,所以其长度为3示例2:输入:s=“bbbbb”输出:1解释:因为无重复字符的最长子串是“b”,所以其长度为1。示例3:输入:s=“pwwkew”输出:3解释:因为无重复字符的最长子串是“wke”,所以其长度为3。请注意,</div>
                    </li>
                    <li><a href="/article/1903843363333926912.htm"
                           title="JavaScript基础-删除事件(解绑事件)" target="_blank">JavaScript基础-删除事件(解绑事件)</a>
                        <span class="text-muted">難釋懷</span>
<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>在现代Web开发中,动态地添加和移除事件处理器是构建交互式网页的关键技能之一。虽然添加事件处理器相对直观,但了解如何有效地移除或“解绑”这些处理器同样重要。这不仅有助于优化性能,还能防止潜在的内存泄漏问题。本文将介绍几种方法来删除JavaScript中的事件处理器,并探讨它们的应用场景及最佳实践。一、为什么需要删除事件?随着页面复杂度的增加,不恰当地管理事件处理器可能会导致性能下降或出现意外行为。</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>