【网络爬虫】(1) 网络请求,urllib库介绍
各位同學好,今天開始和各位分享一下python網絡爬蟲技巧,從基本的函數開始,到項目實戰。那我們開始吧。
1. 基本概念
這里簡單介紹一下后續學習中需要掌握的概念。
(1)http 和 https 協議。http是超文本傳輸,接收HTML頁面的方法,服務器80端口。https是http協議的加密版本,服務端口是443端口。?
(2)URL 統一資源定位符。形如:scheme://host:port/path/?query-string=xxx#anchor
以?https://www.bilibili.com/video/BV1eT4y1Z7NB?p=3 為例
scheme:訪問協議,一般為 http 或 https。
host:主機名,域名。上面的 www.bilibili.com
path:查找路徑。video/BV1eT4y1Z7NB 就是 path
port:端口號,訪問網站時瀏覽器默認 80 端口
query-string:查詢字符串。如上面的 ?p=3,如有多個,用&分隔
anchor:錨點。后臺不用管,是前端用來做頁面定位的。相當于現在停留的位置是網頁的第幾個小節。
注:在瀏覽器中請求一個url,瀏覽器會對url進行編碼。除英文字母,數字和部分符號外,其他全部使用百分號和十六進制碼值進行編碼。中文字詞需要重新編碼后再發送給服務器
(3)常用的請求方法
GET 請求。只從服務器獲取數據下來(下載文件),并不會對服務器資源產生任何影響的時候使用GET請求。
POST 請求。向服務器發送數據(登錄),上傳文件等,會對服務器資源產生影響時使用POST請求
2. urllib 庫
urllib 庫是 python3 中自帶的網絡請求庫,可以模擬瀏覽器的行為,向服務器發送一個請求,并可以保存服務器返回的數據。
2.1 urlopen 函數
用于打開一個遠程的 url 連接,并且向這個連接發出請求,獲取響應結果。返回的結果是一個 https 響應對象,這個響應對象中記錄了本次 https 訪問的響應頭和響應體。
使用方法為:
urllib.request.urlopen(url, data=None, [timeout,]*, cafile=None, capath=None, cadefault=False,context=None)
參數:
url: 需要打開的網址
data:字節流編碼格式,可以用 urllib.parse.urlencode() 和 bytes() 方法轉換參數格式,如果要設置了data參數,則請求方式為POST
timeout: 設置網站的訪問超時時間,單位:秒。若不指定,則使用全局默認時間。若請求超時,則會拋出urllib.error.URLError異常。
返回值:
http.client.HTTPResponse對象: 返回類文件句柄對象,有read(size),readline,readlines,getcode方法。read(size)若不指定size,則全部讀出來。readline讀取第一行。readlines返回值以多行的形式讀出來。
getcode(): 獲取響應狀態。返回200,表示請求成功,返回404,表示網址未找到。
geturl(): 返回請求的url。
from urllib import request# 打開網站,返回響應對象resp
resp = request.urlopen('https://www.baidu.com')# 通過.read()讀取這個網頁的源代碼,相當于在百度頁面右鍵檢查
print(resp.read())
# 返回網頁信息print(resp.getcode()) #狀態碼
# 200
resp.read() 返回類似如下信息,這里只顯示部分
b'<html>\r\n<head>\r\n\t<script>\r\n\t\tlocation.replace(location.href.replace("https://","http://"));
\r\n\t</script>\r\n</head>\r\n<body>\r\n\t<noscript><meta http-equiv="refresh" content="0;
url=http://www.baidu.com/"></noscript>\r\n</body>\r\n</html>'
2.2 urlretrieve 函數
直接將遠程數據下載到本地,方法如下:
rlretrieve(url, filename=None, reporthook=None, data=None)
參數:
url:下載鏈接地址
filename:指定了保存本地路徑,若參數未指定,urllib 會生成一個臨時文件保存數據。
reporthook:是一個回調函數,當連接上服務器、以及相應的數據塊傳輸完畢時會觸發該回調,我們可以利用這個回調函數來顯示當前的下載進度。
data:指 POST 導服務器的數據,該方法返回一個包含兩個元素的( filename,headers ) 元組,filename 表示保存到本地的路徑,header 表示服務器的響應頭
# 將百度的首頁下載到本地
from urllib import request# 下載某一張圖片,傳入圖像的url和保存路徑
request.urlretrieve('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fnimg.ws.126.net%2F%3Furl%3Dhttp%253A%252F%252Fdingyue.ws.126.net%252F2021%252F1010%252F90f82dafj00r0q72d001jc000hs009uc.jpg%26thumbnail%3D650x2147483647%26quality%3D80%26type%3Djpg&refer=http%3A%2F%2Fnimg.ws.126.net&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1642840179&t=888aee0d4f561d7238b290c9da876362', 'C:/Users/admin/Documents/Downloads/test1.jpg')# 下載成功后返回:
('C:/Users/admin/Documents/Downloads/test1.jpg',<http.client.HTTPMessage at 0x26b86c85a60>)
2.3 urlencode 函數
用瀏覽器發送請求時,如果 url 中包含了中文或其他特殊字符,那么瀏覽器會自動進行編碼。
如果使用代碼發送請求,必須手動進行編碼,這時需要 urlencode 函數實現。urlencode 把字典數據轉換為url編碼的數據
方法如下:
urllib.parse.urlencode( 字典 )
下面,對張三使用%和十六進制重新編碼,鍵和鍵之間使用&號連接,空格使用+號連接
from urllib import parse
# 自定義一個字典,后續用于重新編碼
params = {'name':'張三','age':18, 'greet':'hello world'}
# 對字典編碼
result = parse.urlencode(params)
print(result)
# 除英文和數字外都使用 %號和十六進制來編碼# 打印結果
name=%E5%BC%A0%E4%B8%89&age=18&greet=hello+world
實際使用:
如果網址中有中文,需要先將中文從中分割出來,以字典的方式重新編碼轉換后,再拼接到網址中。
from urllib import parse# url = 'https://www.baidu.com/s?wd=周杰倫' # 直接用于網絡請求時,ascii碼不能識別# 使用方法
url = 'https://www.baidu.com/s'# 定義一個字典
params = {'wd':'周杰倫'}
# 對中文編碼
qs = parse.urlencode(params)
print(qs) #打印編碼結果# 拼接到網址url后面
url = url + '?' + qs
print(url)# 網絡請求,得到網頁中的數據
resp = request.urlopen(url)
print(resp.read())
打印結果分別為
wd=%E5%91%A8%E6%9D%B0%E4%BC%A6https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6b'<html>\r\n<head>\r\n\t<script>\r\n\t\tlocation.replace(location.href.replace("https://","http://"));
\r\n\t</script>\r\n</head>\r\n<body>\r\n\t<noscript><meta http-equiv="refresh" content="0;
url=http://www.baidu.com/"></noscript>\r\n</body>\r\n</html>'
2.4?parse_qs 函數
將經過編碼后的 url 參數解碼,返回字典類型,方法如下:
urllib.parse.urlencode( url )
應用:
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%3A=%E5%BC%A0%E4%B8%89&age=18&greet=hello+world解碼后: {'name:': ['張三'], 'age': ['18'], 'greet': ['hello world']}
2.4 urlparse 和 urlsplit 函數
分割 url 中的各個組成部分,分割成 scheme,host,path,params,query-string,anchor,具體含義看最上面。
這兩個函數的區別是:urlsplit 不返回 params,但是這個參數params基本用不到。
(1)urlparse 方法
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
urlstring:?待解析的URL,必填項
scheme:?默認的協議,如 http 或 https 等。
allow_fragments:?即是否忽略fragment。若設為 False,fragment 部分就會被忽略,它會被解析為 path、parameters 或 query 的一部分,而 fragment 部分為空。
返回值為所有分割后的結果
# 使用 urlparse 方法from urllib import parse# 給出一個url網址
url = 'https://blog.csdn.net/dgvv4?spm=1001.5501#1'# 使用 urlparse 解析分割 url 中的組成部分
result = parse.urlparse(url)print(result) # 獲取所有屬性print('scheme:', result.scheme) # 獲取指定屬性
返回值如下:
ParseResult(scheme='https', netloc='blog.csdn.net', path='/dgvv4', params='', query='spm=1001.5501', fragment='1')scheme: https
(2)urlsplit 方法
# 使用 urlsplit 方法from urllib import parse# 給出一個url網址
url = 'https://blog.csdn.net/dgvv4?spm=1001.5501#1'# 使用 urlparse 解析分割 url 中的組成部分
result = parse.urlsplit(url)print(result)print('scheme:', result.scheme)
返回值如下,返回結果沒有params參數
SplitResult(scheme='https', netloc='blog.csdn.net', path='/dgvv4', query='spm=1001.5501', fragment='1')scheme: https
2.5 Request 函數
如果在請求時增加一些請求頭,防止網頁發現是爬蟲,避免爬蟲失敗。那么就必須使用resquest.Resquest()?類來實現。比如要增加一個User-Agent。
from urllib import request, parse# 輸入請求
url = 'http://www.acga......com/'# 輸入瀏覽器頁面的User-Agent請求頭,使請求頭更加像這個瀏覽器
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62','Refer':'http://www.acganime.com/'}# data需要經過urlencode重新編碼后才能傳進去
data = {'first' : True,'pn' : 1, #第幾頁'kd' : 'cos' }
# 重新編碼
data = parse.urlencode(data)
# 編碼類型轉換成utf-8
data = data.encode('utf-8')# 使用request.Request,添加請求頭,只是定義好了一個類,并沒有發送請求
req = request.Request(url, headers=headers, data=data, method='POST') #請求方式為get # 使用 urlopen 方法獲取網頁信息
resp = request.urlopen(req) #傳入添加請求頭后的類
print(resp.read().decode('utf-8')) # 轉換成utf-8顯示結果
返回爬取的網頁數據:
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="renderer" content="webkit">
<!-- <meta name="referrer" content="no-referrer" /> --><meta name="viewport" content="initial-scale=1.0,maximum-scale=5,width=device-width,viewport-fit=cover">
.........................................................
總結
以上是生活随笔為你收集整理的【网络爬虫】(1) 网络请求,urllib库介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【机器视觉案例】(5) AI视觉,远程手
- 下一篇: 【机器视觉案例】(5) AI视觉,手势调