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

我需要使用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的情況下,只能charset的情况下,只能;requests也是用 chardet 进行猜测。
而且,@ferstar 所说的 req.encoding 是用于 响应体(Response.content) 的,并不能用于 headers
;requests也是用 chardet 進行猜測。 而且,@ferstar 所說的 req.encoding 是用於 響應體(Response.content) 的,並不能用於 headers提問者沒提供程式碼和網頁連結之前,我只能用

提問者
給的資料:

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

字符串,不是bytes!所以req.encoding是无效的。
前面我也提到过,这其实是个 URI,从原字符的某个编码转义而来。%URI 仔細看,這是個字串,不是bytes!所以req.encoding是無效的。 前面我也提到過,這其實是個 URI,從原字元的某個編碼
轉義

而來。 %URI

轉義符

還原的方法在上面我已經寫了,結果也是正確的。

為什麼不採納正確的答案呢?


為什麼不採納正確的答案呢?

為什麼不採納正確的答案呢?

本來不想更此貼文了,但@ferstar 評論了一大段,不回就有點不合適了~

在題主更新完善問題後我正好在所以及時跟進了答案,可以得到正確結果解決了題主的問題,這是事實;題主採納我的答案之前你這個答案好像並沒有更新,這也是事實;我之前貼出了相應源碼的具體實現,也是在講道理,這更是事實;我說的req.encoding方法確實起到了作用,而不是像你說的對headers無用,貌似也是事實

引用@ferstar 的評論,完成

SF的內容更新是有
歷史版本記錄

的,翻出來對比一下。

提問者:ider3小时,@ider 更新了问题#r4,并采纳了@ferstar 的第一版错误答案#r1。
采纳回答:同意並接受回答:ferstar
在我更新了正確答案#r3之後3小時,@ider 更新了問題#r4,並採納了@ferstar 的第一版錯誤答案#r1。 採納之後

,我在評論中提出異議,@ferstar 更新了第二版答案#r2。

而且,@ferstar 的第二版答案
依然是錯的gb2312,他不过是替换成兼容编码gbk

🎜但是,為什麼@ferstar 的第二版答案會得到正確的結果呢? 🎜因為之前我找到了正確編碼🎜,他不過是替換成相容編碼gbk而已。 🎜

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

至於這個程序正確的寫法,我也懶得解釋和更新了,累!
除非,@ider 重新採納我的答案,還有可能考慮~~

洪涛

你的檔案名稱是使用 gb2312編碼的,你解碼也需要設定 按照gb2312 解碼,如果按照utf-8解碼,就會出現亂碼。可能你設定過的解碼,預設按照utf-8解碼的

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!