七.Python標準庫:Urllib庫

Urllib庫是Python用于操作Url的標準模塊,Python2.x時分為Urllib和Urllib2,Python3.x時合并到Urllib里面。這里把常見的變化列舉一下,便于查找修改。
官方文檔:https://docs.python.org/3.6/library/urllib.html

Python2.x Python3.x
import urllib2 import urllib.request,urllib.error
import urllib import urllib.request,urllib.error,urllib.parse
import urlparse import urllib.parse
urllib2.urlopen urllib.request.urlopen
urllib2.request urllib.request.Request
urllib.quote urllib.request.quote
urllib.urlencode urllib.parse.urlencode
cookielib.CookieJar http.CookieJar
  1. 簡單讀取網頁信息:urllib需制定內容的解碼方式,requests可自動解碼。
import urllib.request  
f = urllib.request.urlopen('http://python.org/') 
html1 = f.read()   #urlopen返回的是bytes對象,此時調用read()方法得到的也是bytes對象。
html2 = f.read().decode('utf-8')    #要獲取字符串內容,需要指定解碼方式。因此,更常用html2的方式。

#還可以寫成以下方式:
import urllib.request
with urllib.request.urlopen('http://python.org') as f:
    html = f.read().decode('utf-8')
    print(f.status)
    print(html)

#html等價于requests庫的r.text:
import requests
r = requests.get('http://python.org') 
print(r.status_code)
print(r.text)        #調用r.text時,Requests對象會使用其推測的文本編碼自動解碼。
print(r.encoding)    #查詢Requests對象使用的編碼方式。
r.encoding = 'utf-8'  #可直接通過賦值語句來改變Requests對象使用的編碼方式。

2.urllib對含中文的URL進行手動編碼

import urllib.request
a = urllib.request.quote("中文")
b = urllib.request.unquote(a)
print(a,b)

結果為:%E4%B8%AD%E6%96%87 中文

3.使用Request對象添加headers進行請求

import urllib.request
hds = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'}
req = urllib.request.Request('http://python.org')
req.add_header('User-Agent','Mozilla/5.0')  ##注意參數是用“,”進行分隔。
#req.add_header('User-Agent',hds['User-Agent'])  #另一種寫法
with urllib.request.urlopen(req) as f:    ##urlopen可放入url或Request對象
    html = f.read().decode('utf-8')

#requests方法
import requests
hds = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'}
r = requests.get('http://python.org',headers=hds) 

4.超時設置

import urllib.request
#加上timeout參數即可
f = urllib.request.urlopen(req,timeout=1)
f = urllib.request.urlopen('http://python.org',timeout=1)

#完整用法(正常響應1秒,若網站服務器性能不好時可適當調高timeout值)
import urllib.request
for i in range(10):   #若超時,重復請求10次
    try:
        f = urllib.request.urlopen('http://python.org',timeout=1)
        print(f.read().decode('utf-8')[:100])
        break
    except Exception as e:
        print("出現異常: "+str(e))
        # print(type(e))

#requests庫類似
for i in range(10):   #若超時,重復請求10次
    try:
        r = requests.get('http://python.org',timeout=0.25)   #響應比urllib.request快
        print(r.text[:100])
        break
    except Exception as e:
        print("第{}次請求出現異常:".format(str(i+1))+str(e))
        print(type(e))

5.下載HTML文件到本地
同理:圖片、MP3、視頻等文件格式也是用‘wb’形式下載。

#方法一:
import urllib.request

html = urllib.request.urlopen("http://www.baidu.com").read()
with open("1.html","wb") as f:     #使用b模式寫入,此時傳入的html不需解碼
    f.write(html)


#方法二:最方便
#urlretrieve(url, filename=None, reporthook=None, data=None)  
#reporthook(可選)是回調函數,可以顯示下載進度。
#data(可選)指post到服務器的數據。

import urllib.request
urllib.request.urlretrieve("http://www.baidu.com",filename="1.html")
#urllib.request.urlretrieve("http://www.baidu.com","1.html") 


#方法三:
import requests

r = requests.get("http://www.baidu.com")
with open("1.html",'wb') as f:
    f.write(r.content)

# 其他格式:
urllib.request.urlretrieve("XXX.jpg",filename="1.jpg")      #XXX表示服務器地址
urllib.request.urlretrieve("XXX.mp3",filename="1.mp3")
urllib.request.urlretrieve("XXX.rmvb",filename="1.rmvb")

6.get請求實例
get請求的url地址格式:http://網址?字段名1=內容1&字段名2=內容2
http://www.baidu.com/s?wd="python"&rqlang=cn # wd代表關鍵字, rqlang代表區域

import urllib.request

base_url = "http://www.baidu.com/s?wd="
keyword = "Python爬蟲"
url = base_url + urllib.request.quote(keyword)
html = urllib.request.urlopen(url).read()
with open("1.html","wb") as f:
    f.write(html)

#requests庫
import requests

base_url = "http://www.baidu.com/s?wd="
keyword = "Python爬蟲"
url = base_url + keyword     #requests模塊自動解析含中文的url
r = requests.get(url)
#print(r.url)                #可查看解析后的url
with open("2.html","wb") as f:
    f.write(r.content)

7.使用代理:urllib.request.ProxyHandler

import urllib.request  
 
# 創建代理字典
proxy1={'sock5': 'localhost:1080'}
proxy2={'http': '183.51.191.203:9797'}
# 使用ProxyHandler方法生成處理器對象
proxy_handler = urllib.request.ProxyHandler(proxy1) 
# 創建代理IP的opener實例
opener = urllib.request.build_opener(proxy_handler)  
# 創建全局默認的open對象,使用urlopen()時會自動使用已經安裝的opener對象
urllib.request.install_opener(opener) 
  
a = urllib.request.urlopen("http://www.baidu.com").read().decode("utf8")  
print(len(a))

8.開啟Debuglog:urllib.request.HTTPHandler,urllib.request.HTTPSHandler

import urllib.request

http_handler = urllib.request.HTTPHandler(debuglevel=1)
https_handler = urllib.request.HTTPSHandler(debuglevel=1)
opener = urllib.request.build_opener(http_handler,https_handler)
urllib.request.install_opener(opener)
urllib.request.urlopen("https://www.baidu.com")

9.異常處理:URLError,子類HTTPError

  • 觸發URLError的原因有以下四種可能:
    ①連接不上服務器
    ②遠程URL不存在
    ③無網絡
    ④觸發HTTPError
#寫法一:
import urllib.request
import urllib.error

try:
    # urllib.request.urlopen("http://www.google.com")       #對應URLError
    urllib.request.urlopen("https://login.taobao.com/member")   #對應HTTPError
except urllib.error.HTTPError as e:
    print(e.code,e.reason)
except urllib.error.URLError as e:
    print(e.reason)

#寫法二:
import urllib.request
import urllib.error

try:
    #urllib.request.urlopen("http://www.google.com")
    urllib.request.urlopen("https://login.taobao.com/member")
except urllib.error.URLError as e:
    if hasattr(e,"code"):        #hasattr是自帶函數,詳見下方。
        print(e.code)
    if hasattr(e,"reason"):
        print(e.reason)

'''
hasattr(obj, name, /)
    Return whether the object has an attribute with the given name.
    
    This is done by calling getattr(obj, name) and catching AttributeError.
'''
  • HTTP狀態碼以及含義
狀態碼 (e.code) 英文(e.reason) 含義
200 OK 一切正常
301 Moved Permanently 重定向到新的URL,永久性
302 Found 重定向到新的URL,非永久性
304 Not Modified 請求的資源未更新
400 Bad Request 非法請求
401 Unauthorized 請求未經授權
403 Forbidden 禁止訪問
404 Not Found 沒有找到對應頁面
500 Internal Server Error 服務器內部錯誤
501 Not Implemented 服務器不支持實現請求所需要的功能

10.post請求

import urllib.request
import urllib.parse

url = "https://www.douban.com/accounts/login"
params = {'source':'index_nav',
          'form_email':'XXXX',     #賬號
          'form_password':'XXXX'   #密碼
          }
postdata = urllib.parse.urlencode(params).encode('utf-8')  #對數據進行編碼
req = urllib.request.Request(url,postdata)
html = urllib.request.urlopen(req).read()
with open('1.html','wb') as f:
    f.write(html)

#requests庫
import requests
url = "https://www.douban.com/accounts/login"
params = {'source':'index_nav',
          'form_email':'XXXX',     #賬號
          'form_password':'XXXX'   #密碼
          }
r = requests.post(url,params)
with open('1.html','wb') as f:
    f.write(r.content)
#注:
urlencode:對key-value的字典數據進行編碼轉換,返回類似“a=XXX&b=XXX”的結果。
quote:對單個字符串進行編碼轉換,返回編碼后的一串字符,多用于中文字符的編碼。

11.使用cookies

import urllib.request
import urllib.parse
import http.cookiejar
url = "https://www.douban.com/accounts/login"
params = {'source':'index_nav',
          'form_email':'XXXX',     #賬號
          'form_password':'XXXX'   #密碼
          }
postdata = urllib.parse.urlencode(params).encode('utf-8')  #對數據進行編碼
req = request.Request(url, postdata, method="POST")  # 構建Request對象

#創建CookieJar對象
cj = http.cookiejar.CookieJar()
pro = urllib.request.HTTPCookieProcessor(cj)
opener = urllib.request.build_opener(pro)
# 創建全局默認的open對象,使用urlopen()時會自動使用已經安裝的opener對象
urllib.request.install_opener(opener)

html1 = urllib.request.urlopen(req).read()
with open('1.html', 'wb') as f:
    f.write(html1)


#requests庫
import requests
url = "https://www.douban.com/accounts/login"
headers = {
    'Cookie':'xxxxxxx'
}
r = requests.get(url,headers=headers)
print(r.text)
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容