網(wǎng)絡(luò)請求
urlopen函數(shù)用法
urllib庫
urllib庫是python中一個最基本的網(wǎng)絡(luò)請求庫??梢阅M瀏覽器的行為,向指定的服務(wù)器發(fā)送一個請求,并可以保存服務(wù)器返回的數(shù)據(jù)
urlopen函數(shù)
在python3的urllib庫中,所有和網(wǎng)絡(luò)請求相關(guān)的方法都被集成到urllib.request模塊下面了,下面先看下urlopen函數(shù)基本使用:
from
urllib
import
request
resp
=
request
.
urlopen
(
'http://www.baidu.com'
)
print
(
resp
.
read
(
)
)
實(shí)際上,使用瀏覽器訪問百度,右鍵查看源代碼。就會發(fā)現(xiàn),打印處理的內(nèi)容就是和請求的內(nèi)容一摸一樣的,也就是說,上面的三行代碼已經(jīng)幫我們將百度首頁的內(nèi)容全部爬下來了
這里對urlopen函數(shù)進(jìn)行詳細(xì)講解:
- url:請求的url
- data:請求的data,如果設(shè)置了這個值,那么請求將會變成post請求
- 返回值:返回值是一個http.client.HTTPResponse對象,這個對象是一個類文件句柄對象有read(size)、readline、readlines以及getcode等方法
urlretrieve函數(shù)
這個函數(shù)可以方便的將網(wǎng)頁上的一個文件保存到本地。以下代碼可以非常方便的將百度的首頁下載到本地
from
urllib
import
request
request
.
urlretrieve
(
'http://www.baidu.com/'
,
'baidu.html'
)
使用這個函數(shù),可以方便我們將圖片或者其他的內(nèi)容下載到本地
urlencode函數(shù)
用瀏覽器發(fā)送請求的時(shí)候,如果url中包含了中文或者其他特殊符號,那么瀏覽器會自動給我們進(jìn)行編碼,而如果使用代碼發(fā)送請求,那么就必須手動進(jìn)行編碼,這時(shí)候就應(yīng)該使用urlencode函數(shù)來實(shí)現(xiàn),urlencode可以把字典數(shù)據(jù)轉(zhuǎn)換為URL編碼的數(shù)據(jù),示例代碼如下:
from
urllib
import
parse
data
=
{
'name'
:
'爬蟲基礎(chǔ)'
,
'greet'
:
'hello world'
,
'age'
:
100
}
result
=
parse
.
urlencode
(
data
)
print
(
result
)
name
=
%
E7
%
88
%
AC
%
E8
%
99
%
AB
%
E5
%
9F
%
BA
%
E7
%
A1
%
80
&
greet
=
hello
+
world
&
age
=
100
parse_qs函數(shù)
可以將經(jīng)過編碼后的url參數(shù)進(jìn)行解碼(這個是配合上面urlencode函數(shù)配合使用的),示例代碼如下:
from
urllib
import
parse
params
=
{
'name'
:
'張三'
,
'age'
:
18
,
'greet'
:
'hello world'
}
qs
=
parse
.
urlencode
(
params
)
print
(
qs
)
result
=
parse
.
parse_qs
(
qs
)
print
(
result
)
name
=
%
E5
%
BC
%
A0
%
E4
%
B8
%
89
&
age
=
18
&
greet
=
hello
+
world
{
'name'
:
[
'張三'
]
,
'age'
:
[
'18'
]
,
'greet'
:
[
'hello world'
]
}
urlparse和urlsplit
有時(shí)候拿到一個url,想要對這個url中的各個組成部分進(jìn)行分割,那么這時(shí)候就可以使用urlparse或者urlsplit來進(jìn)行分割
首先來看下urlparse
from
urllib
import
parse
url
=
'http://www.baidu.com/s?wb=python&username=abc#1'
result
=
parse
.
urlparse
(
url
)
print
(
result
)
ParseResult
(
scheme
=
'http'
,
netloc
=
'www.baidu.com'
,
path
=
'/s'
,
params
=
''
,
query
=
'wb=python&username=abc'
,
fragment
=
'1'
)
如果僅僅只想獲取中間某一個內(nèi)容,可以使用如下的方式來進(jìn)行獲取
print
(
result
.
scheme
)
http
其次來看下urlsplit
url
=
'http://www.baidu.com/s?wb=python&username=abc#1'
result
=
parse
.
urlsplit
(
url
)
print
(
result
)
SplitResult
(
scheme
=
'http'
,
netloc
=
'www.baidu.com'
,
path
=
'/s'
,
query
=
'wb=python&username=abc'
,
fragment
=
'1'
)
對比可以發(fā)現(xiàn),在使用urlsplit的時(shí)候,中間缺少了一個params的參數(shù),這里的params在現(xiàn)在的爬蟲中間用到的比較少,這里獲取的內(nèi)容就是 ;和?之間的內(nèi)容,如下所示
from
urllib
import
parse
url
=
'http://www.baidu.com/s;hello?wb=python&username=abc#1'
result
=
parse
.
urlparse
(
url
)
print
(
result
)
ParseResult
(
scheme
=
'http'
,
netloc
=
'www.baidu.com'
,
path
=
'/s'
,
params
=
'hello'
,
query
=
'wb=python&username=abc'
,
fragment
=
'1'
)
通常情況下,使用urlparse和urlsplit是一樣的,唯一不一樣的地方就是,urlparse中間多一個params屬性,而urlsplit沒有這個屬性
request.Request類
如果想要在請求的時(shí)候增加一些請求頭,那么就必須使用request.Request來實(shí)現(xiàn)。如果要增加一個User-Agent
from
urllib
import
request
url
=
'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='
# resp = request.urlopen(url)
# print(resp.read())
headers
=
{
'User-Agent'
:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
req
=
request
.
Request
(
url
,
headers
=
headers
)
resp
=
request
.
urlopen
(
req
)
print
(
resp
.
read
(
)
)
在上面的代碼中,如果想要給請求的url加上一個請求頭的話,就需要使用request.Request這個方式將請求的內(nèi)容進(jìn)行一個封裝,這里封裝的請求頭是User-Agent這個請求頭,這里將這里面的內(nèi)容寫上瀏覽器的標(biāo)識;這里需要注意,這里封裝好了之后,是還并沒有發(fā)起請求的,最后還是調(diào)用的request.urlopen方法發(fā)起請求的
注意:這里的這個request.Request方法除了能夠傳遞User-Agent外,還能夠傳遞data和method
如下:
ProxyHandler處理器(代理設(shè)置)
很多網(wǎng)站會檢測某一段時(shí)間某個ip的訪問次數(shù)(通過流量統(tǒng)計(jì),系統(tǒng)日志等),如果訪問次數(shù)多的不像正常人,就會禁止這個ip的訪問,所有我們可以設(shè)置一些代理服務(wù)器,每隔一段時(shí)間換一個代理,就算ip被禁止,依然可以換個ip繼續(xù)爬取
urllib中通過ProxyHandler來設(shè)置使用代理服務(wù)器,下面代碼說明如果使用自定義opener來使用代理
from
urllib
import
request
# 未使用代理
# url = 'http://httpbin.org/ip'
#
# resp = request.urlopen(url)
# print(resp.read())
# -----------------------
# 使用代理的
url
=
'http://httpbin.org/ip'
# 1、使用ProxyHandler,傳入代理構(gòu)建一個handler
handler
=
request
.
ProxyHandler
(
{
'http'
:
'125.110.75.152:9000'
}
)
# 2、使用上面創(chuàng)建的handler構(gòu)建一個opener
opener
=
request
.
build_opener
(
handler
)
# 3、使用opener去發(fā)送一個請求
resp
=
opener
.
open
(
url
)
print
(
resp
.
read
(
)
)
這里需要了解到的就是在使用urlopen的時(shí)候,其實(shí)也是完成構(gòu)建一個handler之后再創(chuàng)建了一個opener,最后發(fā)起的請求,這個過程只是在openurl中間隱藏了
常用的代理有:
西刺免費(fèi)代理IP:https://www.xicidaili.com/nt/
快代理:https://www.kuaidaili.com/
代理云:http://www.dailiyun.com/
在需要測試發(fā)送請求的機(jī)器對應(yīng)的外網(wǎng)地址,可以使用http://httpbin.org/ip方式獲取
小結(jié)
1、代理的原理:在請求目的服務(wù)器之前,先請求代理服務(wù)器,然后讓代理服務(wù)器去請求目的網(wǎng)站,代理服務(wù)器拿到目的網(wǎng)站的數(shù)據(jù)后,再轉(zhuǎn)發(fā)給我們的代碼
2、http://httpbin.org:這個網(wǎng)站可以方便的查看http請求的一些請求
3、在代碼中使用代理:
3.1 使用 urllib.request.ProxyHandler
3.2 傳入一個代理,這個代理是一個字典,字典的key是http或者h(yuǎn)ttps,value是ip:port
3.2 使用上一步創(chuàng)建的handler,以及request.build_handler創(chuàng)建一個opener對象
3.3 使用上一步創(chuàng)建的opener,使用open函數(shù),發(fā)起請求
什么是cookie
在網(wǎng)站中,http請求是無狀態(tài)的,也就是說即使第一次和服務(wù)器連接后并且登陸成功后,第二次請求服務(wù)器依然不能知道當(dāng)前是哪個用戶。cookie的出現(xiàn)就是為了解決這個問題,第一次登陸后服務(wù)器返回一些數(shù)據(jù)(cookie)給瀏覽器,然后瀏覽器保存在本地,當(dāng)該用戶發(fā)送第二次請求的時(shí)候,就會自動的把上傳請求存儲的cookie數(shù)據(jù)自動的攜帶給服務(wù)器,服務(wù)器通過瀏覽器攜帶的數(shù)據(jù)就能判斷當(dāng)前用戶是哪個了。cookie存儲的數(shù)據(jù)量有限,不同的瀏覽器有不同的存儲大小,但一般不操過4KB,因此使用cookie只能存儲一些小量的數(shù)據(jù)
cookie的格式
Set
-
Cookie
;
NAME
-
VALUE
;
Expires
/
Max
-
age
-
DATE
;
Path
-
PATH
;
Domain
-
DOMAIN_NAME
;
SECURE
參數(shù)含義:
NAME:cookie的名字
VALUE:cookie的制
Expires:cookie的過期時(shí)間
Path:cookie作用的域名
Domain:cookie作用的域名
SECURE:是否只在https寫一下起作用
下面以訪問百度為例
可以看到,cookie都是放在Response Headers中間的
使用cookielib庫和HTTPCookieProcessor模擬登陸
Cookie是指網(wǎng)站服務(wù)器為了辨別用戶身份和進(jìn)行Session跟蹤,而存儲在用戶用戶瀏覽器上的文本文件,Cookie可以保持登陸信息到用戶下次與服務(wù)器的會話
這里講點(diǎn)題外話:
要將byte類型轉(zhuǎn)為str類型,轉(zhuǎn)換過程是byte -> decode -> str
要將str類型轉(zhuǎn)為byte類型,轉(zhuǎn)換過程是str -> encode -> byte
示例:
以上的方式是通過瀏覽器首先登陸成功之后,在后面頁面訪問的時(shí)候,通過Request Header中間獲取到的Cookie,將這個Cookie放在請求頭中間,使用代碼進(jìn)行訪問
其實(shí)這樣的方式還不是最好的,Cookie是服務(wù)端發(fā)出的,此時(shí)還是copy的瀏覽器的Cookie,更好的方式則是通過模擬登陸之后自動保存Cookie,最后攜帶這個Cookie發(fā)起后面的請求
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
