【Python爬蟲】一招搞定發送中文HTTP請求頭

有時須要將HTTP 請求頭的值設爲中文,但若是直接設成中文,會拋出異常,例如,下面的代碼爲Chinese 請求頭設置了中文。
from urllib import requesturl = '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)
 
執行這段代碼,會拋出以下的異常。
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-1: ordinal not in range(256)

這個異常代表HTTP 請求頭只能是英文字符和符號,不能是雙字節的文字,如中文。爲了解決這個問題,在設置HTTP 請求頭時須要將中文編碼,而後發送到服務端後,在服務端用一樣的規則解碼。能夠採用多種編碼方式,例如url 編碼,base64 編碼,url 編碼就是在瀏覽器地址欄中若是輸入中文,會將其轉換爲%xx 的形式。如輸入「中國」,會變成E4%B8%AD%E5%9B%BD
對字符串url 編碼,須要使用urllib.parse 模塊的urlencode 函數,解碼要使用unquote 函數,代碼以下:
from urllib.parse import unquote,urlencode# 對中文進行編碼value = urlencode({'name':'李寧'})print(value)# 對中文進行解碼print(unquote(value))
執行這段代碼,會輸出以下結果:
name=%E6%9D%8E%E5%AE%81name=李寧
使用urlencode 函數進行編碼時,須要指定字典類型,不能直接對字符串進行編碼。由於urlencode 函數只能對url 參數進行編碼。
base64 編碼須要使用base64 模塊中的b64encode 函數,解碼使用b64decode 函數,代碼以下:
import base64# 對中文進行編碼base64Value = base64.b64encode(bytes('Python從菜鳥到高手',encoding='utf-8'))print(str(base64Value,'utf-8'))# 對中文進行解碼,並按utf-8編碼格式將解碼後的結果轉換爲字符串print(str(base64.b64decode(base64Value),'utf-8'))
 
b64encode 函數編碼後返回的是bytes 類型,須要使用str 函數將其轉換爲字符串類型。b64decode 函數解碼時須要指定bytes 類型的值,b64decode 函數的返回值也是bytes 類型,因此也須要str 函數將該函數的返回值轉換爲字符串。
下面的例子演示了設置中文HTTP 請求頭,並對其解碼的完整過程。
from urllib import requestfrom urllib.parse import unquote,urlencodeimport base64url = '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':'李寧'}), # 設置中文HTTP請求頭,用url編碼格式 # 設置中文HTTP請求頭,用base64編碼格式 'MyChinese':base64.b64encode(bytes('這是中文HTTP請求頭',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請求頭,url編碼格式req.add_header('Chinese2',urlencode({"國籍":"中國"}))response=request.urlopen(req)# 獲取服務端的響應信息value = response.read().decode('utf-8')print(value)import json# 將返回值轉換爲json對象responseObj = json.loads(value)# 解碼url編碼格式的HTTP請求頭print(unquote(responseObj['headers']['Chinese1']))# 解碼url編碼格式的HTTP請求頭print(unquote(responseObj['headers']['Chinese2']))# 解碼base64編碼格式的HTTP請求頭print(str(base64.b64decode(responseObj['headers']['Mychinese']),'utf-8'))

運行結果如圖1 所示。
圖1 設置中文HTTP請求頭

- EOF -javascript


推薦閱讀  點擊標題可跳轉

Python爬蟲實戰:抓取博客文章列表
java

臥槽,好強大的魔法,竟能讓Python支持方法重載
python

Python裝飾器(decorator)不過如此,是我想多了web

這樣合併Python字典,能夠讓程序的運行效率提升4倍json

Python代碼能夠加密嗎?Python字節碼告訴你!swift

看我用元類(metaclass)花式建立Python類
瀏覽器

你不知道__name__變量是什麼意思嗎?
微信

Python生成器(Generator)最完美解釋app

關注「極客起源」公衆號,加星標,不錯過精彩技術乾貨
函數


本文分享自微信公衆號 - 極客起源(geekculture)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索