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 |
- 簡單讀取網頁信息: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)