【Python爬蟲】一招搞定發(fā)送中文HTTP請(qǐng)求頭
有時(shí)需要將HTTP請(qǐng)求頭的值設(shè)為中文,但如果直接設(shè)成中文,會(huì)拋出異常,例如,下面的代碼為Chinese請(qǐng)求頭設(shè)置了中文。
- from urllib import request
- url = 'http://httpbin.org/post'
- headers = {
- 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36',
- 'Host':'httpbin.org',
- 'Chinese':'李寧',
- }
- req = request.Request(url = url,headers=headers,method="POST")
- request.urlopen(req)
執(zhí)行這段代碼,會(huì)拋出如下的異常。
- UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-1: ordinal not in range(256)
這個(gè)異常表明HTTP請(qǐng)求頭只能是英文字符和符號(hào),不能是雙字節(jié)的文字,如中文。為了解決這個(gè)問題,在設(shè)置HTTP請(qǐng)求頭時(shí)需要將中文編碼,然后發(fā)送到服務(wù)端后,在服務(wù)端用同樣的規(guī)則解碼。可以采用多種編碼方式,例如url編碼,base64編碼,url編碼就是在瀏覽器地址欄中如果輸入中文,會(huì)將其轉(zhuǎn)換為%xx的形式。如輸入“中國(guó)”,會(huì)變成E4%B8%AD%E5%9B%BD。
對(duì)字符串url編碼,需要使用urllib.parse模塊的urlencode函數(shù),解碼要使用unquote函數(shù),代碼如下:
- from urllib.parse import unquote,urlencode
- # 對(duì)中文進(jìn)行編碼
- value = urlencode({'name':'李寧'})
- print(value)
- # 對(duì)中文進(jìn)行解碼
- print(unquote(value))
執(zhí)行這段代碼,會(huì)輸出如下結(jié)果:
- name=%E6%9D%8E%E5%AE%81
- name=李寧
使用urlencode函數(shù)進(jìn)行編碼時(shí),需要指定字典類型,不能直接對(duì)字符串進(jìn)行編碼。因?yàn)閡rlencode函數(shù)只能對(duì)url參數(shù)進(jìn)行編碼。
base64編碼需要使用base64模塊中的b64encode函數(shù),解碼使用b64decode函數(shù),代碼如下:
- import base64
- # 對(duì)中文進(jìn)行編碼
- base64Value = base64.b64encode(bytes('Python從菜鳥到高手',encoding='utf-8'))
- print(str(base64Value,'utf-8'))
- # 對(duì)中文進(jìn)行解碼,并按utf-8編碼格式將解碼后的結(jié)果轉(zhuǎn)換為字符串
- print(str(base64.b64decode(base64Value),'utf-8'))
b64encode函數(shù)編碼后返回的是bytes類型,需要使用str函數(shù)將其轉(zhuǎn)換為字符串類型。b64decode函數(shù)解碼時(shí)需要指定bytes類型的值,b64decode函數(shù)的返回值也是bytes類型,所以也需要str函數(shù)將該函數(shù)的返回值轉(zhuǎn)換為字符串。
下面的例子演示了設(shè)置中文HTTP請(qǐng)求頭,并對(duì)其解碼的完整過程。
- from urllib import request
- from urllib.parse import unquote,urlencode
- import base64
- url = 'http://httpbin.org/post'
- headers = {
- 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36',
- 'Host':'httpbin.org',
- 'Chinese1':urlencode({'name':'李寧'}), # 設(shè)置中文HTTP請(qǐng)求頭,用url編碼格式
- # 設(shè)置中文HTTP請(qǐng)求頭,用base64編碼格式
- 'MyChinese':base64.b64encode(bytes('這是中文HTTP請(qǐng)求頭',encoding='utf-8')),
- 'who':'Python Scrapy'
- }
- dict = {
- 'name':'Bill',
- 'age':30
- }
- data = bytes(urlencode(dict),encoding='utf-8')
- req = request.Request(url = url,data=data,headers=headers,method="POST")
- # 通過add_header方法添加中文HTTP請(qǐng)求頭,url編碼格式
- req.add_header('Chinese2',urlencode({"國(guó)籍":"中國(guó)"}))
- response=request.urlopen(req)
- # 獲取服務(wù)端的響應(yīng)信息
- value = response.read().decode('utf-8')
- print(value)
- import json
- # 將返回值轉(zhuǎn)換為json對(duì)象
- responseObj = json.loads(value)
- # 解碼url編碼格式的HTTP請(qǐng)求頭
- print(unquote(responseObj['headers']['Chinese1']))
- # 解碼url編碼格式的HTTP請(qǐng)求頭
- print(unquote(responseObj['headers']['Chinese2']))
- # 解碼base64編碼格式的HTTP請(qǐng)求頭
- print(str(base64.b64decode(responseObj['headers']['Mychinese']),'utf-8'))
運(yùn)行結(jié)果如圖1所示。
圖1 設(shè)置中文HTTP請(qǐng)求頭
本文轉(zhuǎn)載自微信公眾號(hào)「極客起源」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系極客起源公眾號(hào)。