python - requests headers 解码
黄舟
黄舟 2017-04-18 09:35:48
0
3
830

我需要使用python的requests 下载一些文件,但是文件是中文名的

chrome调试看出来的文件名是

Content-Disposition:attachment; filename=%C9%F1%BC%B6%BB%F5%C0%C9.txt

requests 下载显示的却是乱码

import requests
url = 'http://www.23us.so/modules/article/txtarticle.php?id=156'
req = requests.head(url)
headers = req.headers
print( headers.get('Content-Disposition'))

>> attachment; filename=ÇàÔÆÏÉ·.txt

我试过设置req.encoding 没有效果

怎么把header中的文字恢复出来,requests中似乎没有相关方法
各位可以调试一下

黄舟
黄舟

人生最曼妙的风景,竟是内心的淡定与从容!

全部回复(3)
小葫芦

咳咳, 你应该早点放出具体链接地址的, 我跟进下方法, 放码:

url = 'http://www.23us.so/modules/article/txtarticle.php?id=156'
req = requests.head(url)
headers = req.headers
print(headers.get('Content-Disposition').encode(req.encoding).decode('gbk'))  # gb2312也可以正确解码

结果:

attachment; filename=青云仙路.txt

你让req.encoding自己猜目标的编码方式即可.
requests模块的models.py第 769 行注释说的很清楚, 人家可以自动检测目标网页内容的编码类型, 而具体负责检测编码的代码在这里universaldetector.py
所以我们只需要利用下这个特性编码然后再按utf-8解码即可, 看代码:

import requests


url = "http://www.weather.com.cn/data/cityinfo/101010100.html"
req = requests.get(url)
print(req.text)
print(req.encoding)
print(req.text.encode(req.encoding))
print(req.text.encode(req.encoding).decode('utf-8'))

结果:

{"weatherinfo":{"city":"北京","cityid":"101010100","temp1":"-2℃","temp2":"16℃","weather":"晴","img1":"n0.gif","img2":"d0.gif","ptime":"18:00"}}
ISO-8859-1
b'{"weatherinfo":{"city":"\xe5\x8c\x97\xe4\xba\xac","cityid":"101010100","temp1":"-2\xe2\x84\x83","temp2":"16\xe2\x84\x83","weather":"\xe6\x99\xb4","img1":"n0.gif","img2":"d0.gif","ptime":"18:00"}}'
{"weatherinfo":{"city":"北京","cityid":"101010100","temp1":"-2℃","temp2":"16℃","weather":"晴","img1":"n0.gif","img2":"d0.gif","ptime":"18:00"}}
伊谢尔伦

你把 headers 全部显示出来看看,应该有个 charset 属性。


更新

这个其实是 URI encode,是从 unicode转义得来的。
解码例子如下:

def decodeURI(strURI):
    strURI = strURI.replace('%','')
    URI = ''.join((chr(int(strURI[i:i+4],16)) for i in range(0,len(strURI),4)))
    return URI

n = '%C9%F1%BC%B6%BB%F5%C0%C9'
print(decodeURI(n))

结果:

짱벶믵색짱벶믵색
是韩文~~


再更

后来仔细想了想,也可能是别的编码格式,就拿gb2312试一下。

n = '%C9%F1%BC%B6%BB%F5%C0%C9'
print(bytes.fromhex(n.replace('%','')).decode('gb2312'))

结果是:

神级货郎

觉得这个更靠谱些~
这些方法,在urllib都有,分别是:quoteunquote
例子:

import urllib

n = 'filename=%C9%F1%BC%B6%BB%F5%C0%C9.txt'
filename = urllib.parse.unquote(n,encoding='gb2312')
print(filename)

结果是:

filename=神级货郎.txt

三更

我在讲解原理~
在不知道charset的情况下,只能;requests也是用 chardet 进行猜测。
而且,@ferstar 所说的 req.encoding 是用于 响应体(Response.content) 的,并不能用于 headers
提问者没提供代码和网页链接之前,我只能用提问者给的数据:

filename=%C9%F1%BC%B6%BB%F5%C0%C9.txt

仔细看,这是个字符串,不是bytes!所以req.encoding是无效的。
前面我也提到过,这其实是个 URI,从原字符的某个编码转义而来。%URI转义符
还原的方法在上面我已经写了,结果也是正确的。

为什么不采纳正确的答案呢?

为什么不采纳正确的答案呢?

为什么不采纳正确的答案呢?


本来不想更此帖了,但@ferstar 评论了一大段,不回就有点不合适了~

在题主更新完善问题后我正好在所以及时跟进了答案,可以得到正确结果解决了题主的问题,这是事实;题主采纳我的答案之前你这个答案好像并没有更新,这也是事实;我之前贴出了相应源码的具体实现,也是在讲道理,这更是事实;我说的req.encoding方法确实起到了作用,而不是像你说的对headers无用,貌似也是事实

引用@ferstar 的评论,完毕

SF的内容更新是有历史版本记录的,翻出来对比一下。
提问者:ider
回答:同意并接受
回答:ferstar

在我更新了正确答案#r3之后3小时,@ider 更新了问题#r4,并采纳了@ferstar 的第一版错误答案#r1。
采纳之后,我在评论中提出异议,@ferstar 更新了第二版答案#r2。
而且,@ferstar 的第二版答案依然是错误的

但是,为什么@ferstar 的第二版答案会得出正确的结果呢?
因为之前我找到了正确编码gb2312,他不过是替换成兼容编码gbk是韩文~~

🎜 🎜再更🎜 🎜后来仔细想了想,也可能是别的编码格式,就拿gb2312试一下。🎜 rrreee 🎜结果是:🎜 rrreee 🎜觉得这个更靠谱些~🎜这些方法,在urllib都有,分别是:quoteunquote🎜例子:🎜 rrreee 🎜结果是:🎜 rrreee 🎜 🎜三更🎜 🎜我在讲解原理~🎜在不知道charset的情况下,只能;requests也是用 chardet 进行猜测。🎜而且,@ferstar 所说的 req.encoding 是用于 响应体(Response.content) 的,并不能用于 headers。🎜在提问者没提供代码和网页链接之前,我只能用提问者给的数据:🎜
🎜filename=%C9%F1%BC%B6%BB%F5%C0%C9.txt🎜
🎜仔细看,这是个字符串,不是bytes!所以req.encoding是无效的。🎜前面我也提到过,这其实是个 URI,从原字符的某个编码转义而来。%URI转义符。🎜还原的方法在上面我已经写了,结果也是正确的。🎜 🎜为什么不采纳正确的答案呢?🎜 🎜为什么不采纳正确的答案呢?🎜 🎜为什么不采纳正确的答案呢?🎜 🎜 🎜四🎜 🎜本来不想更此帖了,但@ferstar 评论了一大段,不回就有点不合适了~🎜
🎜在题主更新完善问题后我正好在所以及时跟进了答案,可以得到正确结果解决了题主的问题,这是事实;题主采纳我的答案之前你这个答案好像并没有更新,这也是事实;我之前贴出了相应源码的具体实现,也是在讲道理,这更是事实;我说的req.encoding方法确实起到了作用,而不是像你说的对headers无用,貌似也是事实🎜
🎜引用@ferstar 的评论,完毕🎜 🎜SF的内容更新是有历史版本记录的,翻出来对比一下。🎜提问者:ider🎜回答:同意并接受🎜回答:ferstar🎜 🎜在我更新了正确答案#r3之后3小时,@ider 更新了问题#r4,并采纳了@ferstar 的第一版错误答案#r1。🎜采纳之后,我在评论中提出异议,@ferstar 更新了第二版答案#r2。🎜而且,@ferstar 的第二版答案依然是错误的🎜 🎜但是,为什么@ferstar 的第二版答案会得出正确的结果呢?🎜因为之前我找到了正确编码gb2312,他不过是替换成兼容编码gbk而已。🎜

再说说req.encoding 不能作用于 headers
这个结论依然没变。这是由http原理决定的,headers先于body

至于这个程序正确的写法,我也懒得解释和更新了,累!
除非,@ider 重新采纳我的答案,还有可能考虑一下~~

洪涛

你的文件名是使用 gb2312编码的,你解码也需要设置 按照gb2312 解码,如果按照utf-8解码,就会出现乱码。可能你设置过的解码,默认按照utf-8解码的

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!