0

是否可以仅检索 C#/python 或任何其他指定 URL 的选定部分,以减少网络流量。

例如:我想抓取一个网站并假设有一千个要处理的网址,但我只需要网页的一小部分(跳到 100 并下载接下来的 200 个字节)。

4

1 回答 1

2

读取这么小的部分实际上会增加网络流量(以及服务器负载)。对于您的用例,如果您真的只想要每个资源的一个范围,您可能需要请求Range: bytes=0-1024,并使用流式 API 停止读取(并关闭套接字)在 1024 字节处,即使您获得了整个文件,并且手动挑选出[100:300]你得到的字节。

但在某些情况下,这绝对值得做。假设您试图读取 200MB 文件的第 2 和第 54 兆字节;您不想为了保留其中的 1% 而阅读整个 200MB,对吗?

简单的版本是这样的:您Range在请求中发送一个标头。你可能会回来:

  • 带有标头的206Content-Range响应,正文中仅包含您想要的字节。
  • 一个416表示您的范围无法满足,与 a 一起使用Content-Range表明您应该要求的内容。
  • 任何其他成功响应,整个资源都在正文中。(您可能希望使用“流式传输”API 而不是“一次获取所有内容”API 来处理这种情况,因此您至少可以在 54MB 之后停止阅读。)
  • 任何其他错误,显然。

如果您想提前了解您的请求是否可能满足 406,您应该执行HEAD请求以获取Content-LengthAccept-Ranges标头。但请注意,实际上这些都不是必需的。

另外,请注意,一些服务器处理简单的范围请求,但不是所有所需的全部规范。因此,虽然在单个请求中获取两个范围似乎会比发出两个请求有一些开销,但它也可能增加回退到整个文件的机会,因此可能不值得这样做。

无论如何,我不知道有什么库可以让这一切变得微不足道,但是任何中级 HTTP 库(包括内置于 Python stdlib 和 .NET 中的库)都应该使这变得相对容易。requests我将展示一个在 Python 中以交互方式使用第三方库的示例:

>>> import requests
>>> url = 'http://example.com'
>>> h = requests.head(url)
>>> h.headers['Accept-Ranges']
'bytes'
>>> h.headers['Content-Length']
'1270'
>>> r = requests.get(url, headers={'Range': 'bytes=500-600'})
>>> r.status_code
206
>>> r.headers['Content-Range']
500-600/1270
>>> len(r.text)
101
>>> r.text
' 5em auto;\n        padding: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n '

请注意,HTTP 范围是封闭的——也就是说,Bytes: 500-600包括 500 和 600,所以它的长度是 101,而 Python 的range(500, 600)长度只有 100。在这里很容易犯一个错误。

于 2013-10-25T19:24:44.053 回答