我使用Python的
requests
模块来下载HTML页面。
对于每个 URL,我都会执行此语句 response = requests.get(URL)
,
因此任何 GET 请求的结果都会写入响应变量。
我执行此语句来找出下载的 HTML 页面的字节数:
len(response.text)
。我的想法是,如果我的硬盘上没有同名页面,或者有同名页面,但大小不同,则仅将 HTML 保存到硬盘。如果文件存在,我执行 Path(filepath).stat().st_size
来查找硬盘上文件的大小。问题就出现在这里。由于某种原因,对于任何下载的页面,文件的大小始终比使用 len()
对象的 text
属性调用 response
函数的结果大 6 个字节。如果 len()
返回 7282,则 st_size
为 7288;如果 len()
返回 7216,则 st_size
为 7222,依此类推。我不明白这种行为的原因。我可以在 len()
的结果中添加 6 个字节来比较大小。我想,它会起作用,但我不知道真正的原因。这看起来像是一个黑客。
我尝试使用
curl
命令下载页面,结果是一样的。添加了神奇的 6 个字节。我检查了 10 个不同的页面,6 个字节的差异保持不变。
您观察到的差异可能是由于 Python 计算字符串中字节的方式与文件系统计算文件大小的方式之间的差异所致。 Python 的 len() 函数计算字符串中的字符数,而文件系统计算用于存储文件的字节数。
在Python中,字符串是Unicode字符的序列。当您对字符串调用 len() 时,它返回字符串中的字符数,而不是字节数。
另一方面,当您将字符串保存到文件时,它会存储为字节序列。根据所使用的编码(如 UTF-8),单个字符可以占用多个字节。
当您使用 Path(filepath).stat().st_size 检查文件大小时,您会得到文件的大小(以字节为单位),其中包括用于编码字符和任何潜在元数据的字节。
您看到 6 个字节的一致差异的原因可能是由于固定数量的元数据包含在文件大小中,但不包含在字符串长度中。
为了更准确地比较文件大小和字符串长度,您可以在调用 len() 之前将字符串编码为字节,如下所示:
len(response.text.encode('utf-8'))
。这将为您提供以字节为单位的长度,这应该与文件大小更具可比性。
尝试使用
wb
而不是 response.content
以二进制模式 response.text
保存文件。这可以避免任何换行转换,并且不应添加任何额外的字节进行编码:
with open(filepath, 'wb') as file:
file.write(response.content)
立即比较文件大小,看看差异是否仍然存在。