《爬蟲學習》(二)(urllib庫使用)
urllib
庫是Python
中一個最基本的網路請求庫。可以模擬瀏覽器的行為,向指定的伺服器傳送一個請求,並可以儲存伺服器返回的資料。
1.urlopen函式:
在Python3
的urllib
庫中,所有和網路請求相關的方法,都被集到urllib.request
模組下面了,以先來看下urlopen
函式基本的使用:
from urllib import request
resp = request.urlopen('http://www.baidu.com')
print(resp.read())
實際上,使用瀏覽器訪問百度,右鍵檢視原始碼。你會發現,跟我們剛才打印出來的資料是一模一樣的。也就是說,上面的三行程式碼就已經幫我們把百度的首頁的全部程式碼爬下來了。一個基本的url請求對應的python程式碼真的非常簡單。
以下對urlopen
url
:請求的url。data
:請求的data
,如果設定了這個值,那麼將變成post
請求。- 返回值:返回值是一個
http.client.HTTPResponse
物件,這個物件是一個類檔案控制代碼物件。有read(size)
、readline
、readlines
以及getcode
等方法。
2.urlretrieve函式:
這個函式可以方便的將網頁上的一個檔案儲存到本地。以下程式碼可以非常方便的將百度的首頁下載到本地:
from urllib import request
request.urlretrieve('http://www.baidu.com/','baidu.html')
3.編碼解碼urlencode函式/parse_qs函式:
urlencode函式
用瀏覽器傳送請求的時候,如果url中包含了中文或者其他特殊字元,那麼瀏覽器會自動的給我們進行編碼。而如果使用程式碼傳送請求,那麼就必須手動的進行編碼,這時候就應該使用urlencode
函式來實現。urlencode
可以把字典資料轉換為URL
編碼的資料。示例程式碼如下:
from urllib import parse
data = {'name':'爬蟲基礎','greet':'hello world','age':100}
qs = parse.urlencode(data)
print(qs)
parse_qs函式:
可以將經過編碼後的url引數進行解碼。示例程式碼如下:
from urllib import parse
qs = "name=%E7%88%AC%E8%99%AB%E5%9F%BA%E7%A1%80&greet=hello+world&age=100"
print(parse.parse_qs(qs))
4.urlpares函式/urlsplit函式:
有時候拿到一個url,想要對這個url中的各個組成部分進行分割,那麼這時候就可以使用urlparse
或者是urlsplit
來進行分割。示例程式碼如下:
from urllib import request,parse
url = 'http://www.baidu.com/s?username=zhiliao'
result = parse.urlsplit(url)
# result = parse.urlparse(url)
print('scheme:',result.scheme)
print('netloc:',result.netloc)
print('path:',result.path)
print('query:',result.query)
urlparse
和urlsplit
基本上是一模一樣的。唯一不一樣的地方是,urlparse
裡面多了一個params
屬性,而urlsplit
沒有這個params
屬性。比如有一個url
為:url = 'http://www.baidu.com/s;hello?wd=python&username=abc#1'
,
那麼urlparse
可以獲取到hello
,而urlsplit
不可以獲取到。url
中的params
也用得比較少。
5.request.Request函式:
如果想要在請求的時候增加一些請求頭,那麼就必須使用request.Request
類來實現。比如要增加一個User-Agent
,示例程式碼如下:
from urllib import request
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}
req = request.Request("http://www.baidu.com/",headers=headers)
resp = request.urlopen(req)
print(resp.read())
6.代理器設定(ProxyHandler):
很多網站會檢測某一段時間某個IP的訪問次數(通過流量統計,系統日誌等),如果訪問次數多的不像正常人,它會禁止這個IP的訪問。
所以我們可以設定一些代理伺服器,每隔一段時間換一個代理,就算IP被禁止,依然可以換個IP繼續爬取。
urllib中通過ProxyHandler來設定使用代理伺服器,下面程式碼說明如何使用自定義opener來使用代理:
from urllib import request
# 這個是沒有使用代理的
# resp = request.urlopen('http://httpbin.org/get')
# print(resp.read().decode("utf-8"))
# 這個是使用了代理的
handler = request.ProxyHandler({"http":"218.66.161.88:31769"})
opener = request.build_opener(handler)
req = request.Request("http://httpbin.org/ip")
resp = opener.open(req)
print(resp.read())
程式碼:
from urllib import request from urllib import parse #resp = request.urlopen('https://www.sohu.com')開啟 #print(resp.readlines()) #resp = request.urlretrieve('http://www.jd.com', 'jd.html')下載 # 編碼 # infomation = {'name':'張三', 'age':18, 'code':'niu'} # result = parse.urlencode(infomation) # print(result) # url = "http://www.sogou.com" # par = {'query':'武佩齊'} # qs = parse.urlencode(par) # url = url + "/web?" +qs # request.urlretrieve(url, '1.html') # 解碼 # infomation = {'name':'張三', 'age':18, 'code':'niu'} # qs = parse.urlencode(infomation) # res = parse.parse_qs(qs) # print(res) #解析 # url = 'http://www.baidu.com/s?wd=python&username=jd#1' # # result = parse.urlparse(url) # print(result.netloc) # result = parse.urlsplit(url) # print(result) # 實戰 # url = 'https://search.bilibili.com/all?keyword=opencv&from_source=nav_search_new' # head = { # 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400', # 'Referer': 'https://www.bilibili.com/' # # } # data = { # 'first':'true', # 'pn':1, # 'kd':'opencv' # } # # req = request.Request(url, headers=head,data=parse.urlencode(data).encode('utf-8'), method='GET') # resp = request.urlopen(req) # print(resp.read().decode('utf-8')) # 代理伺服器 # 沒有使用代理 # url = 'http://www.httpbin.org/ip' # resp = request.urlopen(url) # print(resp.read()) # 使用代理 # url = 'http://www.httpbin.org/ip' # # 1.使用request.ProxyHandler建立hander # hander = request.ProxyHandler({"http":"125.123.137.33:9999"}) # # 2.使用request.build_opener建立opener,通過hander # opener = request.build_opener(hander) # # 3.使用opener進行open連線 # resp = opener.open(url) # print(resp.read())
補充:Cookie:
在網站中,http請求是無狀態的。也就是說即使第一次和伺服器連線後並且登入成功後,第二次請求伺服器依然不能知道當前請求是哪個使用者。cookie的出現就是為了解決這個問題,第一次登入後伺服器返回一些資料(cookie)給瀏覽器,然後瀏覽器儲存在本地,當該使用者傳送第二次請求的時候,就會自動的把上次請求儲存的cookie資料自動的攜帶給伺服器,伺服器通過瀏覽器攜帶的資料就能判斷當前使用者是哪個了。cookie儲存的資料量有限,不同的瀏覽器有不同的儲存大小,但一般不超過4KB。因此使用cookie只能儲存一些小量的資料。