Python使用內(nèi)置urllib模塊或第三方庫(kù)requests訪問網(wǎng)絡(luò)資源

前言

更多內(nèi)容,請(qǐng)?jiān)L問我的 個(gè)人博客


Python 訪問網(wǎng)絡(luò)資源有很多方法狰挡,urllib, urllib2, urllib3, httplib, httplib2, requests ,現(xiàn)介紹如下兩種方法:

  • 內(nèi)置的 urllib 模塊
    • 優(yōu)點(diǎn):自帶模塊,無需額外下載第三方庫(kù)
    • 缺點(diǎn):操作繁瑣削饵,缺少高級(jí)功能
  • 第三方庫(kù) requests
    • 優(yōu)點(diǎn):處理URL資源特別方便
    • 缺點(diǎn):需要下載安裝第三方庫(kù)

內(nèi)置的 urllib 模塊

發(fā)起GET請(qǐng)求

主要使用urlopen()方法來發(fā)起請(qǐng)求岩瘦,如下:

from urllib import request

resp = request.urlopen('http://www.baidu.com')
print(resp.read().decode())

訪問的結(jié)果會(huì)是一 個(gè)http.client.HTTPResponse 對(duì)象,使用此對(duì)象的 read() 方法窿撬,則可以獲取訪問網(wǎng)頁(yè)獲得的數(shù)據(jù)启昧。但是要注意的是,獲得的數(shù)據(jù)會(huì)是 bytes 的二進(jìn)制格式劈伴,所以需要 decode() 一下密末,轉(zhuǎn)換成字符串格式。

發(fā)起POST請(qǐng)求

urlopen() 默認(rèn)的訪問方式是GET跛璧,當(dāng)在 urlopen() 方法中傳入data參數(shù)時(shí)严里,則會(huì)發(fā)起POST請(qǐng)求。注意:傳遞的data數(shù)據(jù)需要為bytes格式追城。

設(shè)置timeout參數(shù)還可以設(shè)置超時(shí)時(shí)間田炭,如果請(qǐng)求時(shí)間超出,那么就會(huì)拋出異常漓柑。如下:

from urllib import request

resp = request.urlopen('http://www.baidu.com', data=b'word=hello', timeout=10)
print(resp.read().decode())

添加Headers

通過 urllib 發(fā)起的請(qǐng)求會(huì)有默認(rèn)的一個(gè)Headers:"User-Agent":"Python-urllib/3.6"教硫,指明請(qǐng)求是由 urllib 發(fā)送的。
所以遇到一些驗(yàn)證User-Agent的網(wǎng)站時(shí)辆布,我們需要自定義Headers瞬矩,而這需要借助于urllib.request中的 Request 對(duì)象。

from urllib import request

url = 'http://httpbin.org/get'
headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'}

# 需要使用url和headers生成一個(gè)Request對(duì)象锋玲,然后將其傳入urlopen方法中
req = request.Request(url, headers=headers)
resp = request.urlopen(req)
print(resp.read().decode())

Request對(duì)象

如上所示景用, urlopen() 方法中不止可以傳入字符串格式的url,也可以傳入一個(gè) Request 對(duì)象來擴(kuò)展功能惭蹂,Request 對(duì)象如下:

class urllib.request.Request(url, data=None, headers={},
                                origin_req_host=None,
                                unverifiable=False, 
                                method=None)

構(gòu)造 Request 對(duì)象必須傳入url參數(shù)伞插,data數(shù)據(jù)和headers都是可選的。

最后盾碗, Request 方法可以使用method參數(shù)來自由選擇請(qǐng)求的方法媚污,如PUT,DELETE等等廷雅,默認(rèn)為GET耗美。

添加Cookie

為了在請(qǐng)求時(shí)能帶上Cookie信息,我們需要重新構(gòu)造一個(gè)opener航缀。

使用request.build_opener方法來進(jìn)行構(gòu)造opener商架,將我們想要傳遞的cookie配置到opener中,然后使用這個(gè)opener的open方法來發(fā)起請(qǐng)求芥玉。如下:

from http import cookiejar
from urllib import request

url = 'https://www.baidu.com'
# 創(chuàng)建一個(gè)cookiejar對(duì)象
cookie = cookiejar.CookieJar()
# 使用HTTPCookieProcessor創(chuàng)建cookie處理器
cookies = request.HTTPCookieProcessor(cookie)
# 并以它為參數(shù)創(chuàng)建Opener對(duì)象
opener = request.build_opener(cookies)
# 使用這個(gè)opener來發(fā)起請(qǐng)求
resp = opener.open(url)

# 查看之前的cookie對(duì)象蛇摸,則可以看到訪問百度獲得的cookie
for i in cookie:
    print(i)

或者也可以把這個(gè)生成的opener使用install_opener方法來設(shè)置為全局的。

則之后使用urlopen方法發(fā)起請(qǐng)求時(shí)灿巧,都會(huì)帶上這個(gè)cookie赶袄。

# 將這個(gè)opener設(shè)置為全局的opener
request.install_opener(opener)
resp = request.urlopen(url)

設(shè)置Proxy代理

使用爬蟲來爬取數(shù)據(jù)的時(shí)候诬烹,常常需要使用代理來隱藏我們的真實(shí)IP。如下:

from urllib import request

url = 'http://www.baidu.com'
proxy = {'http':'222.222.222.222:80','https':'222.222.222.222:80'}
# 創(chuàng)建代理處理器
proxies = request.ProxyHandler(proxy)
# 創(chuàng)建opener對(duì)象
opener = request.build_opener(proxies)

resp = opener.open(url)
print(resp.read().decode())

下載數(shù)據(jù)到本地

在我們進(jìn)行網(wǎng)絡(luò)請(qǐng)求時(shí)常常需要保存圖片或音頻等數(shù)據(jù)到本地弃鸦,一種方法是使用python的文件操作绞吁,將read()獲取的數(shù)據(jù)保存到文件中。

而urllib提供了一個(gè)urlretrieve()方法唬格,可以簡(jiǎn)單的直接將請(qǐng)求獲取的數(shù)據(jù)保存成文件家破。如下:

from urllib import request

url = 'http://python.org/'
request.urlretrieve(url, 'python.html')

urlretrieve() 方法傳入的第二個(gè)參數(shù)為文件保存的位置,以及文件名购岗。

注意:urlretrieve() 方法是python2直接移植過來的方法汰聋,以后有可能在某個(gè)版本中棄用。

第三方庫(kù) requests

安裝

由于 requests是第三方庫(kù)喊积,所以要先安裝烹困,如下:

pip install requests

發(fā)起GET請(qǐng)求

直接用 get 方法,如下:

import requests

r = requests.get('http://www.baidu.com/')
print(r.status_code)    #狀態(tài)
print(r.text)   #內(nèi)容

對(duì)于帶參數(shù)的URL乾吻,傳入一個(gè)dict作為params參數(shù)髓梅,如下:

import requests

r = requests.get('http://www.baidu.com/', params={'q': 'python', 'cat': '1001'})
print(r.url)    #實(shí)際請(qǐng)求的URL
print(r.text)

requests的方便之處還在于,對(duì)于特定類型的響應(yīng)绎签,例如JSON枯饿,可以直接獲取,如下:

r = requests.get('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20%3D%202151330&format=json')
r.json()

# {'query': {'count': 1, 'created': '2017-11-17T07:14:12Z', ...

添加Headers

需要傳入HTTP Header時(shí)诡必,我們傳入一個(gè)dict作為headers參數(shù)奢方,如下:

r = requests.get('https://www.baidu.com/', headers={'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'})

獲取響應(yīng)頭,如下:

r.headers
# {Content-Type': 'text/html; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Content-Encoding': 'gzip', ...}

r.headers['Content-Type']
# 'text/html; charset=utf-8'

發(fā)起POST請(qǐng)求

要發(fā)送POST請(qǐng)求爸舒,只需要把get()方法變成post()蟋字,然后傳入data參數(shù)作為POST請(qǐng)求的數(shù)據(jù),如下:

r = requests.post('https://accounts.baidu.com/login', data={'form_email': 'abc@example.com', 'form_password': '123456'})

requests默認(rèn)使用application/x-www-form-urlencoded對(duì)POST數(shù)據(jù)編碼扭勉。如果要傳遞JSON數(shù)據(jù)鹊奖,可以直接傳入json參數(shù),如下:

params = {'key': 'value'}
r = requests.post(url, json=params) #內(nèi)部自動(dòng)序列化為JSON

上傳文件

上傳文件需要更復(fù)雜的編碼格式剖效,但是requests把它簡(jiǎn)化成files參數(shù)嫉入,如下:

upload_files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=upload_files)

在讀取文件時(shí)焰盗,注意務(wù)必使用 'rb' 即二進(jìn)制模式讀取璧尸,這樣獲取的 bytes 長(zhǎng)度才是文件的長(zhǎng)度。

post() 方法替換為 put() 熬拒, delete() 等爷光,就可以以PUT或DELETE方式請(qǐng)求資源。

添加Cookie

在請(qǐng)求中傳入Cookie澎粟,只需準(zhǔn)備一個(gè)dict傳入cookies參數(shù)蛀序,如下:

cs = {'token': '12345', 'status': 'working'}
r = requests.get(url, cookies=cs)

requests對(duì)Cookie做了特殊處理欢瞪,使得我們不必解析Cookie就可以輕松獲取指定的Cookie,如下:

r.cookies['token']
# 12345

指定超時(shí)

要指定超時(shí)徐裸,傳入以秒為單位的timeout參數(shù)遣鼓。超時(shí)分為連接超時(shí)和讀取超時(shí),如下:

try:
    # 3.1秒后連接超時(shí)重贺,27秒后讀取超時(shí)
    r = requests.get(url, timeout=(3.1, 27))
except requests.exceptions.RequestException as e:
    print(e)

超時(shí)重連

def gethtml(url):
    i = 0
    while i < 3:
        try:
            html = requests.get(url, timeout=5).text
            return html
        except requests.exceptions.RequestException:
            i += 1

添加代理

同添加headers方法骑祟,代理參數(shù)也要是一個(gè)dict,如下:

heads = {
    'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'
}
proxy = {
    'http': 'http://120.25.253.234:812',
    'https' 'https://163.125.222.244:8123'
}
r = requests.get('https://www.baidu.com/', headers=heads, proxies=proxy)

更多編程教學(xué)請(qǐng)關(guān)注公眾號(hào):潘高陪你學(xué)編程

image

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末气笙,一起剝皮案震驚了整個(gè)濱河市次企,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌潜圃,老刑警劉巖缸棵,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異谭期,居然都是意外死亡堵第,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門隧出,熙熙樓的掌柜王于貴愁眉苦臉地迎上來型诚,“玉大人,你說我怎么就攤上這事鸳劳≌幔” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵赏廓,是天一觀的道長(zhǎng)涵紊。 經(jīng)常有香客問我,道長(zhǎng)幔摸,這世上最難降的妖魔是什么摸柄? 我笑而不...
    開封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮既忆,結(jié)果婚禮上驱负,老公的妹妹穿的比我還像新娘。我一直安慰自己患雇,他們只是感情好跃脊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著苛吱,像睡著了一般酪术。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天绘雁,我揣著相機(jī)與錄音橡疼,去河邊找鬼。 笑死庐舟,一個(gè)胖子當(dāng)著我的面吹牛欣除,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播挪略,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼耻涛,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了瘟檩?” 一聲冷哼從身側(cè)響起抹缕,我...
    開封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎墨辛,沒想到半個(gè)月后卓研,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡睹簇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年奏赘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片太惠。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡磨淌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凿渊,到底是詐尸還是另有隱情梁只,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布埃脏,位于F島的核電站搪锣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏彩掐。R本人自食惡果不足惜构舟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望堵幽。 院中可真熱鬧狗超,春花似錦、人聲如沸朴下。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桐猬。三九已至麦撵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間溃肪,已是汗流浹背免胃。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惫撰,地道東北人羔沙。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像厨钻,于是被迫代替她去往敵國(guó)和親扼雏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354