requests模塊介紹
相對于python自帶的urllib模塊,requests模塊提供了相對更高層的api來進行網頁訪問的作業,
對于requests模塊,使用很簡單,一般我們會用到兩個函式:
- requests.get(url,params=None,**kwargs) 這里的params是我們要傳入的query,它的格式是dict,
- requests.post(url,data=https://www.cnblogs.com/wxys/p/None,**kwargs) 這里的data就是我們要提交的表單data,也是直接傳入dict就好,
以上兩個函式分別對應http協議中的"GET"方法與"POST"方法,而除了這兩者,還有如"PUT"、"DELETE"、"HEAD"等方法,在requests模塊中有一個統一的函式來發起不同“方法”的http請求報文:
- requests.request(method,url,**kwargs) 可以看到該函式的第一個引數method的取值就是"GET"、"POST"等,
- 該方法與上文提到的兩個方法,回傳值都是requests.Response物件,后面我們會對該物件與requests.Request物件進行介紹
- 較常用的關鍵字引數:params,data,headers,proxies,stream等,
- 其實上文所介紹的兩個函式get和post,或是對應其他方法的函式,它們的實作就是使用request.requests函式的:
def get(url, params=None, **kwargs):
kwargs.setdefault('allow_redirects', True)
#這里可見request.get的實質
return request('get', url, params=params, **kwargs)
這里來詳細介紹一下headers,proxies和stream關鍵字引數的用途:
- headers引數就是http請求報文的頭部,它的格式是一個dict,其中最為常用的headers元素就是User-Agent,模仿瀏覽器訪問網頁,
- proxies引數就是代理,它的格式也是一個dict,每一個鍵值對是這樣的形式:"協議":"ip:port",
- stream引數是相對前兩者較陌生的一個引數,該引數默認為False,意味著我們會一下子把網頁內容都下載,但如果主動設定為True的話,則不會立刻下載網頁內容,而是等到使用requests.Response的iter_content才會迭代地把資料下載并讀進記憶體中,
requests.Request&requests.Response
這兩個物件詳細對爬蟲有過了解的朋友們都很熟悉了,它們是在爬蟲邏輯中很關鍵的兩個物件,簡單來說: 發出Request,回傳Response ,
requests.Request
我們在使用requests時一般不會直接創建Request物件,所以這里我們大致了解一下即可:
requests.Request(method=None, url=None, headers=None, data=https://www.cnblogs.com/wxys/p/None, params=None) 我們列出Request類構造時所需的一些常用引數,并且前文我們提到requests.get等函式的實質是requests.request函式,那么其實研究該函式的原始碼:
def request(method, url, **kwargs):
with sessions.Session() as session:
#可以看到在request函式內呼叫了session.request方法
return session.request(method=method, url=url, **kwargs)
#這個是session.request方法的定義
def request(self, method, url,
params=None, data=https://www.cnblogs.com/wxys/p/None, headers=None, cookies=None, files=None,
auth=None, timeout=None, allow_redirects=True, proxies=None,
hooks=None, stream=None, verify=None, cert=None, json=None):
#可以看到這里其實使用傳入引數
#創建了一個requests.Request實體
req = Request(
method=method.upper(),
url=url,
headers=headers,
files=files,
data=data or {},
json=json,
params=params or {},
auth=auth,
cookies=cookies,
hooks=hooks,
)
#進一步處理,得到對應的PreparedRequest物件
prep = self.prepare_request(req)
proxies = proxies or {}
settings = self.merge_environment_settings(
prep.url, proxies, stream, verify, cert
)
# Send the request.
send_kwargs = {'timeout': timeout,
'allow_redirects': allow_redirects,
}
send_kwargs.update(settings)
#這里是真正的send Request,并回傳一個Response物件
resp = self.send(prep, **send_kwargs)
return resp
由以上代碼可知,其實requests.request方法的實質就是創建一個Request實體,在對其進行一定預處理后將其send,然后得到Response,
requests.Response
我們之前的requests.get、requests.post或是requests.request函式的回傳物件就是一個requests.Response實體,對于Response類,我們主要介紹幾個常用屬性與方法:
- Response.content 以bytes的形式得到回傳Response的內容,其實也就是未解碼的html檔案
- Response.text 文本形式的Response內容,也就是解碼了的html檔案,且如Response.encoding屬性為None的話,那么會以chardet去猜測bytes內容的編碼方式,當然我們也可以在access這個屬性前人為指定一種編碼方式,
- Response.encoding 指定以何種方式來解碼,Response內容的編碼完全基于HTTP報頭,遵循RFC2616檔案,
- Response.url 即Response的url
- Response.status_code 相應的狀態碼,如成功的話該值就是200
- Response.request 得到對應于這個Response的Request物件,其實是(PreparedRequest),通過這個request物件我們可以得到當時訪問時的url、method、headers等屬性,
- Response.iter_content(chunk_size=1),該函式回傳一個generator,其中的chunk_size決定我們每次下載并讀進記憶體中多少個位元組,一般使用方法為for item in Response.iter_content(256)這樣的for回圈遍歷即可,
BeautifulSoup
BeautifulSoup是一個可以從HTML或XML檔案中提取資料的Python庫,通常我們使用requests得到html檔案(Response.text),然后我們再使用BeautifulSoup來處理,從而提取到我們需要的資訊,
如何使用BeautifulSoup
from bs4 import BeautifulSoup #其中html是回傳的網頁文本,也就是response.text #而lxml是BeautifulSoup使用的檔案決議器,需要我們 #已經預先pip install好lxml這個模塊,或者我們也可 #使用python自帶的html.parser,不過它的速度較慢些 #而soup就是一個BeautifulSoup物件,它承載了一個 #由html檔案內部各個元素所形成的樹形結構, soup=BeautifulSoup(html,"lxml") #以下就是幾個最簡單基本的使用 #直接以屬性參考的方式得到html檔案中的第一個a標簽 print(soup.a) #進一步得到html檔案中第一個a標簽的中的字串部分(如果存在的話) print(soup.a.string) #拿到html檔案中第一個a標簽的href屬性的值 print(soup.a["href"])
以上大致介紹了BeautifulSoup的簡單實用,接下來我們進行更詳細地分析:
BeautifulSoup將HTML檔案轉換成一個復雜的樹形結構,該樹形結構中的每個節點都是Python物件,所有物件可分為4種: Tag、NavigableString、BeautifulSoup、Comment,
- Tag物件 對應的就是html檔案中的標簽,它有很多屬性與方法,這里先介紹它最重要的兩個屬性:1.tag.name回傳的就是該tag標簽的名字(比如tag對應a標簽,那么tag.name回傳的就是"a"),2.tag.attrs以字典的形式回傳該標簽所有的屬性,如{"herf":"www.baidu.com"},而我們想拿到屬性值就可以用tag.attrs["href"],不過上文也看到了,這里其實可以直接簡寫為tag["href"],
- NavigableString物件 它其實就是我們使用soup.a.string時真正回傳的物件,它是對python自帶的string物件進行了一個包裝,我們可以就把它當作string使用,不需要在意其它,
- BeautifulSoup物件 它對應我們檔案的全部內容,也就是上文的soup物件,大部分時間我們可以把它當作tag物件一樣來使用 方法 ,不過它沒有attrs屬性,并且它的name屬性的值只為:["document"],
- Comment物件 它對應html檔案中的注釋標簽:<!-- 此處寫注釋 -->,該標簽很特別的是它不會被瀏覽器顯示,只是一個對程式員注釋的作用,該物件在實際應用中很少使用,這里不作更進一步的介紹,
接下來我們要來對tag物件以及BeautifulSoup物件在使用 method 上進行更進一步的介紹:
而所謂的method使用,我們著眼的就是在得到的BeautifulSoup物件的樹形結構中對所需要的資訊進行搜索的作業,
這樣的搜索作業根據對 節點本身資訊 和 節點之間在樹形結構中的關系 的應用不同而 分為兩種 ,
第一種,由節點本身資訊對節點進行搜索:
所謂tag.a其實就是tag.find("a"),該方法的具體函式頭如下
find(name,attrs,recursive,string,**kwargs)
name就是標簽名,它的值是一個“過濾器”,
attrs就是該name對應標簽的屬性,同樣值也是一個“過濾器”,
recursive是一個bool值,默認為True,它的意思是搜索當前tag的所有子孫節點,如果為False,則只搜索當前tag的直接子節點
string就是該name對應的string值,也是一個“過濾器”,
**kwargs一般使用不用理會,
當然上面的tag.a或是tag.find("a")都只能得到tag下的第一個a標簽,
這太局限了,如果我們想要的是后面的第三個a標簽呢?于是就有了
tag.find_all("a")方法,回傳一個串列,來得到所有的a標簽,簡寫為tag("a"),
find_all(name,attrs,recursive,string,**kwargs)
引數的意義和find函式一樣
下面我們來講解一下這個所謂的“過濾器”到底是什么東西
具體的代碼實作有點繁瑣,總之我們可以把它理解為一種
物件,我們允許這個物件有多種值,
(1)字串值 最簡單的就是傳入字串值,如之前的tag.a
(2)正則運算式值 即re.compile(r"\d+")這樣的形式
(3)串列值 如name=["a","div"],則find只會回傳其中的后者,
find_all會回傳一個串列,包含tag下的所有a和div標簽,
(4)True 意思不做過濾,對于find是回傳tag下符合要求的標簽的第一個,對于find_all是回傳所有,比如name=True,那么就不對name
過濾,對其他attrs或string繼續篩選過濾,
第二種,根據節點所在樹形結構中的關系對其它節點進行搜索:
直接子節點: tag.childern和tag.contents是tag物件的兩個屬性,注意不是對應標簽的屬性!!!它們回傳當前tag節點在樹形結構中的直接子節點, tag.childern回傳一個生成器 tag.contents回傳一個串列 子孫節點: tag.descendants回傳一個生成器,對它進行遍歷可以得到當前tag節點的所有子孫節點的回圈遍歷結果, 直接父節點: tag.parent獲取當前tag的直接父節點 所以父節點: tag.parents回傳一個生成器,可以獲取當前tag的所有父輩節點 next的兄弟節點: tag.next_sibling和tag.next_siblings,回傳值型別不用贅述, previous的兄弟節點: tag.previous_sibling和tag.previous_siblings,同樣回傳型別不用贅述,
以上大概就是BeautifulSoup在搜索資訊時所需的知識,其它如兩種方式結合的tag.find_parent(name,attrs,recursive,string,**kwargs)等方法,之后可以慢慢了解,
想要原始碼或者更多內容點擊這里即可獲取
此文轉載文,著作權歸作者所有,如有侵權聯系小編洗掉!
原文地址:https://www.tuicool.com/articles/uAbyimr
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/157690.html
標籤:Python
