<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
urllib
是Python中請求url連線的官方標準庫,就是你安裝了python,這個庫就已經可以直接使用了,基本上涵蓋了基礎的網路請求功能。在Python2中主要為urllib和urllib2,在Python3中整合成了urllib。
Python3.x中將urllib2
合併到了urllib
,之後此包分成了以下四個模組:
它支援如下協定的URL處理:file,ftp,gopher,hdl,http,https,imap,mailto,mms,news,nntp,prospero,rsync,rtsp,rtspu,sftp,sip,sips,snews,svn,snv+ssh,telnet,wais
語法:urllib.parse.urlparse(urlstring,scheme='',allow_fragments=True)
可以傳遞3個引數
該方法可以實現URL的識別和分段,分別是scheme(協定),netloc(域名),path(路徑),params(引數),query(查詢條件),fragment(錨點)
import urllib.parse url = "http://www.baidu.com" parsed = urllib.parse.urlparse(url) print(parsed) # 輸出:ParseResult(scheme='http', netloc='www.baidu.com', path='', params='', query='', fragment='') #返回的是一個parseresult型別的元組物件,可以通過屬性或者索引來獲取值
與urlparse()相反,urlunparse通過列表或者元祖的形式接受一個可迭代的物件,實現URL構造
from urllib.parse import urlunparse data=['http','www.baidu.com','index.html','user','a=6','comment'] print(urlunparse(data)) #構造一個完整的URL #output #http://www.baidu.com/index.html;user?a=6#comment
與urlparse()方法類似,它會返回5個部分,只是把params合併到path中。
from urllib.parse import urlsplit result = urlsplit('http://www.baidu.com/index.html;user?id=5#comment') print(result) print(result.query) # output # SplitResult(scheme='http', netloc='www.baidu.com', path='/index.html;user', query='id=5', fragment='comment') # id=5
與urlunparse()類似,它也是將連結的各部分組合完整的連結的方法,傳入的引數也是可迭代的物件,如列表元祖等,唯一的區別是長度必須是5個,它省略了params
from urllib.parse import urlsplit,urlunsplit data=['http','www.baidu.com','index.html','a=5','comment'] result=urlunsplit(data) print(result) #output #http://www.baidu.com/index.html?a=5#comment
urlencode() 將dict中的鍵值對以連線符&劃分。
urlencode()在構造GET請求引數時很有用,可以將字典型別的請求資料轉變為url編碼
import urllib.parse dic = {'name':'melon','age':18} data = urllib.parse.urlencode(dic) print(data) #age=18&name=melon
parse_qs()與urlencode()正好相反,它是用來反序列化的,如將GET引數轉換回字典格式
from urllib.parse import urlencode,parse_qs,urlsplit params = {'username':'zs','password':'123'} base_url='http://www.baidu.com' url=base_url+'?'+urlencode(params) #將字典轉化為get引數 query=urlsplit(url).query #獲去URL的query引數條件 print(parse_qs(query)) #根據獲取的GET引數轉換為字典格式 #output #{'username': ['zs'], 'password': ['123']}
quote:URL編碼處理,該方法可以將內容轉換為URL編碼的格式。
如引數中帶有中文等非ASCII碼時,有時會導致亂碼的問題,此時用這個方法將中文字元轉化為URL編碼
from urllib.parse import quote key='中文' url='https://www.baidu.com/s?key='+quote(key) print(url) #output #https://www.baidu.com/s?key=%E4%B8%AD%E6%96%87
unquote(url):URL解碼處理,與quote()相反,URL上的特殊字元還原
from urllib.parse import quote, urlsplit, unquote key = '中文' url = 'https://www.baidu.com/s?key=' + quote(key) print(url) unq = urlsplit(url).query.split('=')[1] # 獲取引數值 print(unquote(unq)) # 解碼引數
格式:urljoin(baseurl,newurl,allowFrag=None)
通過將基本URL(base)與另一個URL(url)組合起來構建完整URL,它會使用基本URL元件,協定(schemm)、域名(netloc)、路徑(path)、來提供給URL中缺失的部分進行補充,最後返回結果。
base_url提供了三項內容scheme,netloc,path,如果這3項在新的連結中不存在就給予補充,如果新的連結存在就使用新的連結部分,而base_url中的params,query和fragment是不起作用的。
通過urljoin()方法可以實現連結的解析、拼接和生成。
import urllib.parse url = "http://www.baidu.com" new_path = urllib.parse.urljoin(url, "index.html") print(new_path) # 輸出:<a href="http://www.baidu.com/index.html" rel="external nofollow" target="_blank">http://www.baidu.com/index.html</a>
urlretrieve(url,filename,reporthook,data)
不寫路徑filename則會被存為臨時檔案,可以用 urllib.urlcleanup() 來清除快取
file_name = urllib.request.urlretrieve('http://www.baidu.com','%s/baidu.html'%BASE_DIR)
模組中最常用的函數為urlopen():
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
引數如下:
urlopen返回http.client.HTTPResponse物件,提供方法:
在urlopen()方法中,直接寫入要存取的url地址字串,該方法就會主動的存取目標網址,然後返回存取結果。
返回的存取結果是一個http.client.HTTPResponse物件,使用該物件的read()方法即可獲取存取網頁獲取的資料,這個資料是二進位制格式的,所以我們還需要使用decode()方法來將獲取的二進位制資料進行解碼,轉換成我們可以看的懂得字串。
import urllib.request req = urllib.request.urlopen('http://www.baidu.com') print(req.read().decode()) print(req.getheaders()) # 以列表元祖對的形式返回響應頭資訊 print(req.getheader('Content-Type')) # 返回響應頭中的Content-Type值 print(req.info()) # 返回網頁的頭資訊 print(req.info()['Content-Type']) # 返回響應頭中的Content-Type值
不需要使用read()方法 。
for line in urlopen('https://。。.html'): line = line.decode('utf-8') # Decoding the binary data to text. if 'EST' in line or 'EDT' in line: # look for Eastern Time print(line)
GET請求和我們平常get存取方式一樣,直接把引數寫到網址上面就好了。
import urllib.request import urllib.parse dic = {'name':'melon','age':18} data = urllib.parse.urlencode(dic) req = urllib.request.urlopen('http://127.0.0.1:8000/index?%s'%data) #通過urlopen方法存取拼接好的url content = req.read()
在urlopen()
方法中,urlopen()
預設的存取方式是GET,當在urlopen()
方法中傳入data引數時,則會發起POST請求。
注意:傳遞的data資料需要為bytes格式,如data=b'word=hello'。
import urllib.request import urllib.parse import json dic = {'name':'melon','age':18} data = urllib.parse.urlencode(dic) req = urllib.request.Request('http://127.0.0.1:8000/index', data.encode()) #encode:將url編碼型別的請求資料轉變為bytes型別 opener = urllib.request.urlopen(req) content = json.loads(opener.read().decode()) #read()方法是讀取返回bytes資料內容,decode轉換後為str
當我們需要模擬一些其他的引數的時候,簡單的urlopen()
方法已經無法滿足我們的需求了,這個時候我們就需要使用下面的urllib.request
中的Request
物件來幫助我們實現一些其它引數的模擬,比如請求頭。
Request
物件如下所示:
# Request物件範例化 req = urllib.request.Request(url, data=None, headers={},origin_req_host=None,unverifiable=False, method=None)
from urllib import request url='http://httpbin.org/post' headers={ 'User-Agent':'Mozilla/5.0 (compatible; MSIE 5.5; Windows NT)', 'Host':'httpbin.org' } #定義頭資訊 dict={'name':'germey'} data = bytes(parse.urlencode(dict),encoding='utf-8') req = request.Request(url=url,data=data,headers=headers,method='POST') #req.add_header('User-Agent','Mozilla/5.0 (compatible; MSIE 8.4; Windows NT') #也可以request的方法來新增 resp = request.urlopen(req) print(resp.read().decode())
BaseHandler類:
在urllib.request模組裡的BaseHandler類,他是所有其他Handler的父類別,他是一個處理器,比如用它來處理登入驗證,處理cookies,代理設定,重定向等
BaseHandler的子類包括:
build_opener(*handlers)方法用於構建一個自定義的OpenerDirector物件。
build.opener(handler1,handler2…)
之前的urlopen()方法就是urllib提供的一個Opener,通過Handler處理器來構建Opener實現Cookies處理,代理設定,密碼設定等
Opener的方法包括:
設定全域性後既可以用urlopen()方法, 也可以用opener.open() ,不安裝的話只能用opener.open()方法
# 將這個opener設定為全域性的opener,之後所有的,不管是opener.open()還是urlopen() 傳送請求,都將使用自定義 request.install_opener(opener) resp = request.urlopen(url)
HTTPPasswordMgrWithDefaultRealm()類建立一個密碼管理物件,用來儲存HTTP請求相關的使用者名稱和密碼,主要應用兩個場景:
在下面的方法中我們還用到了一個新的東西,即request.build_opener()方法,其實urlopen()就是通過構造好了的opener物件傳送請求,在這裡我們使用request.build_opener()方法重構了一個opener()物件,我們可以通過這個物件實現urlopen()實現的任何東西。
from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler,build_opener from urllib.error import URLError username='username' passowrd='password' url='http://localhost' p=HTTPPasswordMgrWithDefaultRealm() #構造密碼管理範例 p.add_password(None,url,username,passowrd) #新增使用者名稱和密碼到範例中 auth_handler=HTTPBasicAuthHandler(p) #傳遞密碼管理範例構建一個驗證範例 opener=build_opener(auth_handler) #構建一個Opener try: result=opener.open(url) #開啟連結,完成驗證,返回的結果是驗證後的頁面內容 html=result.read().decode('utf-8') print(html) except URLError as e: print(e.reason)
使用爬蟲來爬取資料的時候,如果過於頻繁的存取,而且網站還設有限制的話,很有可能會禁封我們的ip地址,這個時候就需要設定代理,來隱藏我們的真實IP。
urllib提供了urllib.request.ProxyHandler()方法可動態的設定代理IP池。將代理IP以字典形式傳入該方法,然後通過urllib.reques.build_opener()建立opener物件,用該物件的open()方法向伺服器傳送請求。
from urllib import request url = 'http://httpbin.org/ip' proxy = {'http': '218.18.232.26:80', 'https': '218.18.232.26:80'} proxies = request.ProxyHandler(proxy) # 建立代理處理器 opener = request.build_opener(proxies) # 建立opener物件 resp = opener.open(url) print(resp.read().decode())
有時候當我們存取一些網站的時候需要進行翻頁或者跳轉等其它操作,為了防止無法存取我們想要的資料,需要讓網站識別我們是同一個使用者。這個時候我們就需要帶上cookie進行存取。
在設定cookie的時候由於urllib並沒有很好的處理cookie的物件,所以在這裡我們需要用到一個別的庫,即http庫,並使用裡面的cookiejar來進行cookie的管理:
CookieJar類關係:CookieJar —-派生—->FileCookieJar —-派生—–>MozillaCookieJar和LWPCookieJar
from http import cookiejar from urllib import request cookie = cookiejar.CookieJar() # 建立一個cookiejar物件 cookies = request.HTTPCookieProcessor(cookie) # 使用HTTPCookieProcessor建立cookie處理器 opener = request.build_opener(cookies) # 並以它為引數建立Opener物件 resp = opener.open('https://www.baidu.com') # 使用這個opener來發起請求 # 檢視之前的cookie物件,則可以看到存取百度獲得的cookie for i in cookie: print(i)
cookies儲存到檔案:
1、以Mozilla型瀏覽器的cookies格式:
cookie=http.cookiejar.MozillaCookieJar(filename=fielname)
import http.cookiejar,urllib.request fielname='cookies.txt' cookie=http.cookiejar.MozillaCookieJar(filename=fielname) #建立儲存cookie的範例,儲存瀏覽器型別的Mozilla的cookie格式 handler=urllib.request.HTTPCookieProcessor(cookie) #構建一個handler opener=urllib.request.build_opener(handler) #構建Opener response=opener.open('http://www.baidu.com') #請求 cookie.save(ignore_discard=True,ignore_expires=True)
從檔案中讀取cookies:
2、也可以儲存為libwww-perl(LWP)格式的Cookies檔案
cookie=http.cookiejar.LWPCookieJar(filename=fielname)
import http.cookiejar,urllib.request #fielname='cookiesLWP.txt' #cookie=http.cookiejar.LWPCookieJar(filename=fielname) #LWP格式的cookies cookie=http.cookiejar.LWPCookieJar() cookie.load('cookiesLWP.txt',ignore_discard=True,ignore_expires=True) handler=urllib.request.HTTPCookieProcessor(cookie) #構建一個handler opener=urllib.request.build_opener(handler) #構建Opener response=opener.open('http://www.baidu.com') #請求 print(response.read().decode('utf-8'))
當然,如果把上面這個生成的opener物件使用install_opener方法來設定為全域性的,opener物件之後的每次存取都會帶上這個cookie。
通過新增忽略ssl證書驗證關閉證書驗證,由於urllib並沒有很好的處理ssl的物件,所以在這裡我們需要用到一個別的庫,即ssl庫,如下:
import ssl from urllib import request context = ssl._create_unverified_context() res = urllib.request.urlopen(request, context=context)
當你 urllib.urlopen一個 https 的時候會驗證一次 SSL 證書,當目標使用的是自簽名的證書時就會出現一個URLError,如果是這樣可以在開頭加上
import ssl ssl._create_default_https_context = ssl._create_unverified_context
urllib的error模組定義了由request模組產生的異常,如果出現問題,request模組便會丟擲error模組中定義的異常。
在urllib中主要設定了兩個異常,一個是URLError,一個是HTTPError,HTTPError是URLError的子類。
URLError類來自urllib庫的error模組,它繼承自OSError類,是error異常模組的基礎類別,由request模組產生的異常都可以通過捕獲這個類來處理
它只有一個屬性reason,即返回錯誤的原因
from urllib import request,error try: response=request.urlopen('https://hehe,com/index') except error.URLError as e: print(e.reason) #如果網頁不存在不會丟擲異常,而是返回捕獲的異常錯誤的原因(Not Found)
reason如超時則返回一個物件
import socket import urllib.request import urllib.error try: response=urllib.request.urlopen('https://www.baidu.com',timeout=0.001) except urllib.error.URLError as e: print(e.reason) if isinstance(e.reason,socket.timeout): print('time out')
它是URLError的子類,專門用來處理HTTP請求錯誤,比如認證請求失敗,它有3個屬性:
舉例:
from urllib import request,error try: response=request.urlopen('http://cuiqingcai.com/index.htm') except error.HTTPError as e: #先捕獲子類異常 print(e.reason,e.code,e.headers,sep='n') except error.URLError as e: #再捕獲父類別異常 print(e.reason) else: print('request successfully')
利用urllib的robotparser模組,我們可以實現網站Robots協定的分析
也稱為爬蟲協定、機器人協定,它的全名叫做網路爬蟲排除標準(Robots Exclusion Protocol),用來告訴爬蟲和搜尋引擎哪些網頁可以抓取,哪些不可以抓取,它通常是一個robots.txt的文字檔案,一般放在網站的根目錄下。
當搜尋爬蟲存取一個站點時,它首先會檢查這個站點根目錄下是否存在robots.txt檔案,如果存在,搜尋爬蟲會根據其中定義的爬去範圍來爬取,如果沒有找到,搜尋爬蟲會存取所有可直接存取的頁面
我們來看下robots.txt的樣例:
User-agent: * Disallow: / Allow: /public/
它實現了對所有搜尋爬蟲只允許爬取public目錄的功能,將上述內容儲存為robots.txt檔案放在網站根目錄下,和網站的入口檔案(index.html)放在一起
1、User-agent描述了搜尋爬蟲的名稱,將其設定為*則代表協定對任何爬蟲有效,如設定為Baiduspider則代表規則對百度爬蟲有效,如果有多條則對多個爬蟲受到限制,但至少需要指定一條
一些常見的搜尋爬蟲名稱:
2、Disallow指定了不允許抓取的目錄,如上例中設定的/則代表不允許抓取所有的頁面
3、Allow一般和Disallow一起使用,用來排除單獨的某些限制,如上例中設定為/public/則表示所有頁面不允許抓取,但可以抓取public目錄
設定範例:
#禁止所有爬蟲 User-agent: * Disallow: / #允許所有爬蟲存取任何目錄,另外把檔案留空也可以 User-agent: * Disallow: #禁止所有爬蟲存取某那些目錄 User-agent: * Disallow: /home/ Disallow: /tmp/ #只允許某一個爬蟲存取 User-agent: BaiduSpider Disallow: User-agent: * Disallow: /
用來解析robots.txt,該模組提供了一個類RobotFileParser,它可以根據某網站的robots.txt檔案來判斷一個抓取爬蟲時都有許可權來抓取這個網頁
urllib.robotparser.RobotFileParser(url='')
robotparser類常用的方法:
from urllib.robotparser import RobotFileParser rp = RobotFileParser() #建立物件 rp.set_url('https://www.cnblogs.com/robots.txt') #設定robots.txt連線,也可以在建立物件時指定 rp.read() #讀取和解析檔案 print(rp.can_fetch('*','https://i.cnblogs.com/EditPosts.aspx?postid=9170312&update=1')) #判斷連結是否可以被抓取
urllib3增加了連線池等功能,兩者互相都有補充的部分。許多Python的原生系統已經開始使用urllib3。
urllib3提供了很多python標準庫urllib裡所沒有的重要特性:
urllib3是一個第三方庫,pip安裝:
pip install urllib3
通過urllib3存取一個網頁,那麼必須首先構造一個PoolManager物件,然後通過PoolMagent中的request方法或者 urlopen()方法來存取一個網頁,兩者幾乎沒有任何區別。
class urllib3.poolmanager.PoolManager(num_pools = 10,headers = None,** connection_pool_kw )
生成一個PoolManager所需要的引數:
當存取網頁完成之後,將會返回一個HTTPResponse物件。
使用request()或者urlopen(),獲取GET請求的響應內容:
import urllib3 data = json.dumps({'abc': '123'}) http = urllib3.PoolManager(num_pools=5, headers={'User-Agent': 'ABCDE'}) resp1 = http.request('GET', 'http://www.baidu.com', body=data) resp2 = http.urlopen('GET', 'http://www.baidu.com', body=data) print(resp2.data.decode())
使用request()或者urlopen(),進行 POST 請求:
import urllib3 import json data = json.dumps({'abc': '123'}) http = urllib3.PoolManager(num_pools=5, headers={'User-Agent': 'ABCDE'}) resp1 = http.request('POST', 'http://www.httpbin.org/post', body=data,timeout=5,retries=5) #resp2 = http.urlopen('POST', 'http://www.httpbin.org/post', body=data,timeout=5,retries=5) print(resp1.data.decode())
注意事項:urllib3 並沒有辦法單獨設定cookie,所以如果你想使用cookie的話,可以將cookie放入到headers中
urlopen()比request()有三個引數是不一樣的,你會發現request()具有fields,headers兩個引數。所以更多的也就使用 request() 方法了。
推薦使用request()來進行存取的,因為使用request()來進行存取有兩點好處,
語法:
如果你需要使用代理來存取某個網站的話, 那麼你可以使用 ProxyManager 物件來進行設定
def __init__(self, proxy_url, num_pools=10, headers=None,proxy_headers=None, **connection_pool_kw):
ProxyManager和PoolManager的方法基本完全相同。
import urllib3 import json data = {'abc': '123'} proxy = urllib3.ProxyManager('http://50.233.137.33:80', headers={'connection': 'keep-alive'}) resp1 = proxy.request('POST', 'http://www.httpbin.org/post', fields=data) print(resp1.data.decode())
到此這篇關於Python網路程式設計之HTTP使用者端模組urllib與urllib3的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45