requests-html庫輕體驗-HTMLSession下載表情包
阿新 • • 發佈:2020-07-25
requests-html實戰,HTMLSession下載鬥圖啦最新表情包
前言
在這篇文章之前,我寫了requests入門實踐02_下載鬥圖拉最新表情包用正則表示式提取url,來下載鬥圖啦最新表情包,前幾天我去檢視時,直接就翻車了,程式碼根本提取不到表情包的URL咯,昨天意外看到一個視訊,想到了直接用html解析庫來改造(沒錯2020年7月我才想到用html解析庫來處理響應, 這博主是真的菜).
依賴庫
該指令碼檔案使用了:requests庫, requests-html庫, loguru庫(可選,如果不需要,你得把檔案中logger/loguru相關的內容給幹掉)
安裝方法: pip install requests requests-html loguru
requests-html
官方文件:
https://requests.readthedocs.io/projects/requests-html/en/latest/
https://cncert.github.io/requests-html-doc-cn/#/
全面支援解析JavaScript!
CSS 選擇器 (jQuery風格, 感謝PyQuery).
XPath 選擇器, for the faint at heart.
自定義user-agent (就像一個真正的web瀏覽器).
自動追蹤重定向.
連線池與cookie持久化.
令人欣喜的請求體驗,魔法般的解析頁面.
-
該指令碼用的方法概覽:
from requests_html import HTMLSession # 相當於requests.Session(),它會自動記錄並在所有請求之間持久儲存cookie session = HTMLSession() # 請求方法,引數與requests一致 res = session.get(url='http://www.baidu.com/') # 提取響應的html檔案中所有的超連結(相對路徑提取):注意只能提取到 <a herf="提取到這裡的連結"> res.html.links # 絕對url路徑提取 res.html.absolute_links # 通過css查詢指定元素,(這需要一點css基礎???) about = res.html.find('#about', first=True) # 解析:從響應的html檔案中,查詢ID為about的元素,first=True只返回第一個,first=False返回所有,返回值是一個list # 通過xpath查詢指定元素,返回一個list (這就需要xpath基礎了) res.html.xpath("//div[contains(@class,'page-content')]//a//img/@data-original") # 解析:// - html根目錄,div[contains(@class, 'page-content')] - class為contains的div元素,下面的 class為page-content的元素, //a//img - 元素下的a標籤下的img標籤 , /@data-original - 屬性為data-original的值 # 通過查詢到的element元素,得到下方所有的屬性與值,返回形式是dict about.attrs
指令碼一覽
# 安裝:pip install requests (必須) # 安裝:pip install requests-html (必須) # 安裝:pip install loguru (可選) # HTMLSession 同步會話 import time from requests_html import HTMLSession # 建立檔案目錄 import os # 日誌庫 from loguru import logger """ 為避免下載重複圖片,請選擇註釋掉文中不需要的檔名稱處理方法,也可任意組合下載方法,檔名稱處理方法 """ class Dowanlod_Image(object): def __init__(self, save_path='./img/'): """ :param save_path: 檔案儲存目錄,預設當前目錄下新建img資料夾 """ self.save_path = save_path # 日誌存放位置 logger.add(f"file_{time.time()}.log") # 建立目錄存放檔案 os.makedirs(save_path, exist_ok=True) logger.info(f'{save_path.split("/")[-1]}資料夾建立成功.') # 同步會話例項 self.session = HTMLSession() self.headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/84.0.4147.89 Safari/537.36', } logger.info(f'session已例項化:{self.session}.') @logger.catch def main(self, start_page: int = 1, end_page: int = 2): """ :param start_page: 預設引數,從第x頁開始下載 :param end_page: 預設引數,下載第y頁之前的 :return: """ for index in range(start_page, end_page): # 訪問鬥圖啦最新表情第index頁 base_url = f'https://www.doutula.com/photo/list/?page={index}' res = self.session.get(url=base_url, headers=self.headers) logger.info(f'請求{base_url}後得到的響應html{res.text}.') # 含links方法只能獲取 a herf標籤 # print(res.html.absolute_links, '\n', type(res.html.absolute_links)) # 圖片url 提取 :方法1 # 選取element物件-css查詢,first=True,只返回第一個,False返回所有 img_element = res.html.find('.page-content .col-xs-6 img', first=False) logger.info(f'通過css查詢.page-content .col-xs-6 img,得到的所有element物件.') # 圖片url 提取: 方法2 # xpath 直接提取出圖片的連結,列表形式返回 img_url_list = res.html.xpath("//div[contains(@class,'page-content')]//a//img/@data-original") logger.info(f'通過xpath查詢到img標籤中data-original屬性的值,也就是我們需要的圖片url.') # 檔名稱處理:適配圖片url提取-方法1 for data in img_element: # attrs返回element物件所有的屬性字典 # 圖片實際url img_url = data.attrs.get('data-original') # 檔案字尾名 img_suffix = img_url.split('.')[-1] # 完整檔名 img_name = data.attrs.get('alt').join(['', f'.{img_suffix}']) # 檔名稱處理,不能包含:\ / : * ? " < > | wor_list = ['\\', '/', ':', '*', '?', '"', '<', '>', '|'] for wor in wor_list: if wor in img_name: img_name = img_name.replace(wor, '_') # print(img_url, img_name) self.req_download(img_url, img_name) # 檔名稱處理:適配圖片url提取-方法2: 這種方法整體簡潔,但是沒有中文檔名 for img_url in img_url_list: img_name = img_url.split('/')[-1] # print(img_url, img_name) self.ute_download(img_url, img_name) def ute_download(self, img_url, img_name): # 下載圖片方法1:全適配 from urllib.request import urlretrieve # 傳入url, 檔案儲存路徑 urlretrieve(img_url, f'./{self.save_path}{img_name}') logger.info(f'{img_name}下載完成.') def req_download(self, img_url, img_name): # 下載圖片方法2:全適配 # 需單獨請求圖片url介面 rep = self.session.get(img_url, headers=self.headers) with open(f'{self.save_path}{img_name}', 'wb') as f: # 寫入二進位制檔案 f.write(rep.content) logger.info(f'{img_name}下載完成.') if __name__ == '__main__': start_time = time.time() d_img = Dowanlod_Image() d_img.main(2, 3) end_time = time.time() run_time = end_time - start_time logger.debug("=====================") logger.info(f'執行耗時{run_time}.')
實際結果
參考資料
https://www.cnblogs.com/-wenli/p/10160351.html
https://requests.readthedocs.io/projects/requests-html/en/latest/
https://cncert.github.io/requests-html-doc-cn/#/?id=element類