相對於python自帶的urllib模塊,requests模塊提供了相對更高層的api來進行網頁訪問的工做。html
對於requests模塊,使用很簡單,通常咱們會用到兩個函數:python
以上兩個函數分別對應http協議中的"GET"方法與"POST"方法,除了這二者,還有如"PUT"、"DELETE"等方法,在requests模塊中有一個統一的函數來發起不一樣「方法」的http請求報文:程序員
def get(url, params=None, **kwargs): kwargs.setdefault('allow_redirects', True) #這裏可見request.get的實質 return request('get', url, params=params, **kwargs)
這裏來詳細介紹一下headers,proxies和stream關鍵字參數的用途:正則表達式
這兩個對象詳細對爬蟲有過了解的朋友們都很熟悉了,它們是在爬蟲邏輯中很關鍵的兩個對象,簡單來講:發出Request,返回Response。json
咱們在使用requests時通常不會直接建立Request對象,因此這裏咱們大體瞭解一下便可:api
requests.Request(method=None, url=None, headers=None, data=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=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。cookie
咱們以前的requests.get、requests.post或是requests.request函數的返回對象就是一個requests.Response實例。對於Response類,咱們主要介紹幾個經常使用屬性與方法:session
BeautifulSoup是一個能夠從HTML或XML文件中提取數據的Python庫,一般咱們使用requests獲得html文件(Response.text),而後咱們再使用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對象以及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)等方法,以後能夠慢慢了解。