Python爬蟲入門:Urllib庫使用詳解(模擬CSDN登錄)

urllib是基于http的高層庫娇钱,它有以下三個主要功能:
(1)request處理客戶端的請求
(2)response處理服務(wù)端的響應(yīng)
(3)parse會解析url

一网梢、爬取網(wǎng)頁內(nèi)容

我們知道,網(wǎng)頁上呈現(xiàn)的優(yōu)美頁面增热,本質(zhì)都是一段段的HTML代碼填硕,加上JS 、CSS等缕陕,本人也是剛開始學(xué)python,這個文章也比較小白疙挺,資深老鳥請忽略~~扛邑。

本文所說的代碼都是基于python3的,使用phython2的請注意

python 3.x中urllib庫和urilib2庫合并成了urllib庫
其中urllib2.urlopen()變成了urllib.request.urlopen()
urllib2.Request()變成了urllib.request.Request()

那么獲取網(wǎng)頁有哪一些方法呢铐然?這里列舉了三種方法蔬崩,具體查看代碼。

import urllib.request
import http.cookiejar

url = 'http://www.baidu.com'

#直接通過url來獲取網(wǎng)頁數(shù)據(jù)
print('第一種 :直接通過url來獲取網(wǎng)頁數(shù)據(jù)')
response = urllib.request.urlopen(url)
html = response.read()
mystr = html.decode("utf8")
response.close()
print(mystr)

#構(gòu)建request對象進行網(wǎng)頁數(shù)據(jù)獲取
print('第二種 :構(gòu)建request對象進行網(wǎng)頁數(shù)據(jù)獲取')
request = urllib.request.Request(url)
request.add_header('user-agent', 'Mozilla/5.0')
response2 = urllib.request.urlopen(request)
html2 = response2.read()
mystr2 = html2.decode("utf8")
response2.close()
print(mystr2)


#使用cookies來獲取 需要import http.cookiejar
print('第三種:使用cookies來獲取')
cj = http.cookiejar.LWPCookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
urllib.request.install_opener(opener)
response3 = urllib.request.urlopen(url)
print(cj)
html3 = response3.read()
mystr3 = html3.decode("utf8")
response3.close()
print(mystr3)

將上面的代碼copy之后搀暑,在pycharm新建一個python項目舱殿,如下圖,新建一個python file 险掀,命名為demo.py 黏貼上面的代碼


2017-08-06_000707.png

右鍵運行改文件沪袭,我們就可以從控制臺獲取到整個網(wǎng)頁內(nèi)容了


2017-08-06_001041.png

或者打開pycharm的terminal窗口,輸入

python demo.py
2017-08-06_002714.png

copy上面網(wǎng)頁內(nèi)容樟氢,然后黏貼到下面的在線HTML 運行工具
http://www.5axxw.com/tools/web/web_run.html

2017-08-06_001302.png

運行之后我們可以看到下圖網(wǎng)址部分是本地的冈绊,對比網(wǎng)頁的百度,發(fā)現(xiàn)底部的那些網(wǎng)頁新聞不見了埠啃,因為我們抓取的是靜態(tài)網(wǎng)頁呀死宣,動態(tài)網(wǎng)頁需要的一些參數(shù),要如何傳遞給他碴开,下面有簡單的解釋毅该。利用這個我們也可以只抓取我們需要的靜態(tài)網(wǎng)頁,相當(dāng)于做了一些去廣告之類的潦牛。眶掌。。巴碗。朴爬。

2017-08-06_001451.png

從代碼看出,上面使用的urlopen方法橡淆,傳入一個URL召噩,這個網(wǎng)址是百度首頁,協(xié)議是HTTP協(xié)議逸爵,當(dāng)然你也可以把HTTP換做FTP,FILE,HTTPS 等等具滴,只是代表了一種協(xié)議,urlopen一般接受三個參數(shù)师倔,它的參數(shù)如下:

urlopen(url, data, timeout)

第一個參數(shù)url即為URL构韵,第二個參數(shù)data是訪問URL時要傳送的數(shù)據(jù),第三個timeout是設(shè)置超時時間。

第二三個參數(shù)是可以不傳送的贞绳,data默認為空None谷醉,timeout默認為 socket._GLOBAL_DEFAULT_TIMEOUT

第一個參數(shù)URL是必須要傳送的,在這個例子里面我們傳送了百度的URL冈闭,執(zhí)行urlopen方法之后俱尼,返回一個response對象,返回信息便保存在這里面萎攒。

response.read()

response對象有一個read方法遇八,可以返回獲取到的網(wǎng)頁內(nèi)容,我們可以的到一個HTML格式的文檔耍休。

二刃永、構(gòu)造Request

其實上面的urlopen參數(shù)也可以傳入一個Request類的實例,我們構(gòu)造request時需要傳入Url,Data等等的內(nèi)容羊精。

import urllib.request  
req = urllib.request.Request('http://python.org/')  
response = urllib.request.urlopen(req)  
the_page = response.read()  

三斯够、發(fā)送數(shù)據(jù)

http協(xié)議有六種請求方法,get,head,put,delete,post,options喧锦,數(shù)據(jù)傳送最基本的就是POST和GET兩種方式读规,其他方式這里也不進行擴展。
這里我們結(jié)合CSDN的登錄進行介紹
打開以下網(wǎng)頁 https://passport.csdn.net/account/login?from=http://my.csdn.net/my/mycsdn 我們可以看到需要我們輸入一個是賬號燃少,一個是密碼束亏。

2017-08-06_005312.png

點擊登錄之后,網(wǎng)頁就是利用post的方式阵具,把上面兩個輸入項作為參數(shù)碍遍,動態(tài)的發(fā)送過去了。

import urllib.parse
import urllib.request

values = {}
values['username'] = "XXXXXXX@qq.com"
values['password'] = "XXXXXXX"

user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers = {'User-Agent': user_agent}

data = urllib.parse.urlencode(values).encode('UTF8')//這里不encode會類型報錯
url = "https://passport.csdn.net/account/login?from=http://my.csdn.net/my/mycsdn"
request = urllib.request.Request(url, data, headers)
response = urllib.request.urlopen(request)
the_page = response.read()
print(the_page.decode("utf8"))

運行之后我們發(fā)現(xiàn)又跳回了登錄界面阳液,里面我們看到返回網(wǎng)頁中有這么一段注釋:

<!-- 該參數(shù)可以理解成每個需要登錄的用戶都有一個流水號怕敬。只有有了webflow發(fā)放的有效的流水號,用戶才可以說明是已經(jīng)進入了webflow流程趁舀。否則赖捌,沒有流水號的情況下祝沸,webflow會認為用戶還沒有進入webflow流程
矮烹,從而會重新進入一次webflow流程,從而會重新出現(xiàn)登錄界面罩锐。 -->
<input type="hidden" name="lt" value="LT-481574-sCMBpUSfbcMhRTP5imPR5ir9dd0Ett" />
<input type="hidden" name="execution" value="e1s1" />
<input type="hidden" name="_eventId" value="submit" />

于是我們需要添加這個參數(shù)奉狈,然后登錄就成功了,請看代碼

import urllib.parse, urllib.request, http.cookiejar, re

cookie = http.cookiejar.CookieJar()
cookieProc = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(cookieProc)
h = opener.open('https://passport.csdn.net').read().decode("utf8")
patten1 = re.compile(r'name="lt" value="(.*?)"')
patten2 = re.compile(r'name="execution" value="(.*?)"')
b1 = patten1.search(h)
b2 = patten2.search(h)
postData = {
    'username': 'csdn用戶名',
    'password': 'csdn密碼',
    'lt': b1.group(1),
    'execution': b2.group(1),
    '_eventId': 'submit',
}

postData = urllib.parse.urlencode(postData).encode('UTF8')

opener.addheaders = [('Origin', 'https://passport.csdn.net'),
                     ('User-Agent',
                      'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'),
                     ('Referer', 'https://passport.csdn.net/account/login?from=http://my.csdn.net/my/mycsdn')
                     ]
response = opener.open('https://passport.csdn.net', postData)
text = response.read().decode('utf-8', 'ignore')
print(text)

response2 = opener.open('http://my.csdn.net/my/mycsdn')
text2 = response2.read().decode('utf-8', 'ignore')
print(text2)
2017-08-06_014940.png

GET方式:

上面我們使用的是post的形式的涩惑,至于GET方式區(qū)別就是在URL上仁期,我們?nèi)绻苯影褏?shù)寫到網(wǎng)址上面,構(gòu)建一個帶參數(shù)的URL。

values={}
values['username'] = "XXXXX@qq.com"
values['password']="XXXX"
data = urllib.parse.urlencode(values) 
url = "http://passport.csdn.net/account/login"
geturl = url + "?"+data

使用 HTTP 的 PUT 和 DELETE 方法
有時候需要用到PUT方式或者DELETE方式請求跛蛋。

PUT:這個方法比較少見熬的。HTML表單也不支持這個。本質(zhì)上來講赊级, PUT和POST極為相似押框,都是向服務(wù)器發(fā)送數(shù)據(jù),但它們之間有一個重要區(qū)別理逊,PUT通常指定了資源的存放位置橡伞,而POST則沒有,POST的數(shù)據(jù)存放位置由服務(wù)器自己決定晋被。
DELETE:刪除某一個資源兑徘。基本上這個也很少見羡洛,不過還是有一些地方比如amazon的S3云服務(wù)里面就用的這個方法來刪除資源挂脑。
如果要使用 HTTP PUT 和 DELETE ,只能使用比較低層的 httplib 庫欲侮。雖然如此最域,我們還是能通過下面的方式,使 urllib 能夠發(fā)出 PUT 或DELETE 的請求锈麸,不過用的次數(shù)的確是少镀脂,在這里提一下。

import urllib.request
request = urllib.request.Request(uri, data=data)
request.get_method = lambda: 'PUT' # or 'DELETE'
response = urllib.request.urlopen(request)

四忘伞、添加頭部

我們知道薄翅,很多網(wǎng)站,如果不設(shè)置請求頭部屬性氓奈,根本就不會得到響應(yīng)翘魄,而且有一些還要求匹配頭部的某些屬性,所以我們需要去模擬正常訪問的頭部設(shè)置舀奶。那么我們怎么獲取這個headers的屬性呢暑竟?
這個需要借助我們的Chrome瀏覽器了络它。F12打開你需要爬取的網(wǎng)頁幔荒,打開網(wǎng)絡(luò)監(jiān)聽

2017-08-09_004310.png

起初右邊是沒有多少信息的,然后點擊登錄彼城,我們可以看到捕獲到了很多信息涧至,我們選取第一個腹躁,點擊header,就可以查看到我們需要的一些信息了南蓬。具體headers各個屬性的作用纺非,請參閱Http Headers各屬性的作用

2017-08-09_013951.png

其中哑了,agent就是請求的身份,如果沒有寫入請求身份烧颖,那么服務(wù)器不一定會響應(yīng)弱左,所以可以在headers中設(shè)置agent,當(dāng)我們設(shè)置leheaders炕淮,在構(gòu)建request時傳入科贬,到了請求時,就會加入headers傳送鳖悠,服務(wù)器若識別了是瀏覽器發(fā)來的請求榜掌,就會得到響應(yīng)。
另外乘综,我們還有對付”反盜鏈”的方式憎账,對付防盜鏈,服務(wù)器會識別headers中的referer是不是它自己卡辰,如果不是胞皱,有的服務(wù)器不會響應(yīng),所以我們還可以在headers中加入referer

cookie = http.cookiejar.CookieJar()
cookieProc = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(cookieProc)
opener.addheaders = [('Origin', 'https://passport.csdn.net'),
                     ('User-Agent',
                      'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'),
                     ('Referer', '需要添加頭部的網(wǎng)址')
                     ]

五九妈、http 錯誤

import urllib.request  
req = urllib.request.Request(' ')  
try:  
urllib.request.urlopen(req)  
except urllib.error.HTTPError as e:  
print(e.code)  
print(e.read().decode("utf8"))  

六反砌、異常處理

except HTTPError as e:
except URLError as e:

from urllib.request import Request, urlopen  
from urllib.error import URLError, HTTPError  
req = Request("http://www..net /")  
try:  
response = urlopen(req)  
except HTTPError as e:  
print('The server couldn't fulfill the request.')  
print('Error code: ', e.code)  
except URLError as e:  
print('We failed to reach a server.')  
print('Reason: ', e.reason)  
else:  
print("good!")  
print(response.read().decode("utf8"))  

except URLError as e:
if hasattr(e, 'reason'):
elif hasattr(e, 'code'):

from urllib.request import Request, urlopen  
from urllib.error import  URLError  
req = Request("http://www.Python.org/")  
try:  
response = urlopen(req)  
except URLError as e:  
if hasattr(e, 'reason'):  
print('We failed to reach a server.')  
print('Reason: ', e.reason)  
elif hasattr(e, 'code'):  
print('The server couldn't fulfill the request.')  
print('Error code: ', e.code)  
else:  
print("good!")  
print(response.read().decode("utf8"))  

七、HTTP 認證

import urllib.request  
# create a password manager  
password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()  
# Add the username and password.  
# If we knew the realm, we could use it instead of None.  
top_level_url = ""  
password_mgr.add_password(None, top_level_url, 'rekfan', 'xxxxxx')  
handler = urllib.request.HTTPBasicAuthHandler(password_mgr)  
# create "opener" (OpenerDirector instance)  
opener = urllib.request.build_opener(handler)  
# use the opener to fetch a URL  
a_url = ""  
x = opener.open(a_url)  
print(x.read())  
# Install the opener.  
# Now all calls to urllib.request.urlopen use our opener.  
urllib.request.install_opener(opener)  
a = urllib.request.urlopen(a_url).read().decode('utf8')  
print(a)  

八萌朱、使用代理

urllib 默認會使用環(huán)境變量 http_proxy 來設(shè)置 HTTP Proxy宴树。假如一個網(wǎng)站它會檢測某一段時間某個IP 的訪問次數(shù),如果訪問次數(shù)過多晶疼,它會禁止你的訪問酒贬。所以你可以設(shè)置一些代理服務(wù)器來幫助你做工作,每隔一段時間換一個代理翠霍,網(wǎng)站君都不知道是誰在搗鬼了锭吨!

下面一段代碼說明了代理的設(shè)置用法

import urllib.request  
enable_proxy = True
proxy_support = urllib.request.ProxyHandler({'sock5': 'localhost:1080'})  
null_proxy_handler = urllib.request.ProxyHandler({})
if enable_proxy:
    opener = urllib.request.build_opener(proxy_support)  
else:
  opener = urllib.request.build_opener(null_proxy_handler)
urllib.request.install_opener(opener)  
a = urllib.request.urlopen("").read().decode("utf8")  
print(a)  

九、超時

import socket  
import urllib.request  
# timeout in seconds  
timeout = 2  
socket.setdefaulttimeout(timeout)  
# this call to urllib.request.urlopen now uses the default timeout  
# we have set in the socket module  
req = urllib.request.Request('')  
a = urllib.request.urlopen(req).read()  
print(a)  

上面已經(jīng)說過urlopen方法了寒匙,第三個參數(shù)就是timeout的設(shè)置零如,可以設(shè)置等待多久超時,為了解決一些網(wǎng)站實在響應(yīng)過慢而造成的影響锄弱。
例如下面的代碼,如果第二個參數(shù)data為空那么要特別指定是timeout是多少考蕾,寫明形參。

import urllib.request
response = urllib.request.urlopen('http://www.baidu.com', timeout=10)

如果data已經(jīng)傳入棵癣,則不必聲明辕翰。

import urllib.request
response = urllib.request.urlopen('http://www.baidu.com',data, 10)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市狈谊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖河劝,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壁榕,死亡現(xiàn)場離奇詭異,居然都是意外死亡赎瞎,警方通過查閱死者的電腦和手機牌里,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來务甥,“玉大人牡辽,你說我怎么就攤上這事〕伲” “怎么了态辛?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長挺尿。 經(jīng)常有香客問我奏黑,道長,這世上最難降的妖魔是什么编矾? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任熟史,我火速辦了婚禮,結(jié)果婚禮上窄俏,老公的妹妹穿的比我還像新娘蹂匹。我一直安慰自己,他們只是感情好凹蜈,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布怒详。 她就那樣靜靜地躺著,像睡著了一般踪区。 火紅的嫁衣襯著肌膚如雪昆烁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天缎岗,我揣著相機與錄音静尼,去河邊找鬼。 笑死传泊,一個胖子當(dāng)著我的面吹牛鼠渺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播眷细,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼拦盹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了溪椎?” 一聲冷哼從身側(cè)響起普舆,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤恬口,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后沼侣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祖能,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年蛾洛,在試婚紗的時候發(fā)現(xiàn)自己被綠了养铸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡轧膘,死狀恐怖钞螟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谎碍,我是刑警寧澤鳞滨,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站椿浓,受9級特大地震影響太援,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扳碍,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一提岔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笋敞,春花似錦碱蒙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至趁餐,卻和暖如春喷兼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背后雷。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工季惯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人臀突。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓勉抓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親候学。 傳聞我的和親對象是個殘疾皇子藕筋,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容