requests 中的參數 stream


這個參數不常用,不過很巧妙的一個參數.

當下載大的文件的時候,建議使用strea模式.

默認情況下是stream=Ffalse,他會立即開始下載文件並存放到內存當中,倘若文件過大就會導致內存不足的情況.

當把get函數的stream參數設置成True時,它不會立即開始下載,當你使用iter_content或iter_lines遍歷內容或訪問內容屬性時才開始下載。需要注意一點:文件沒有下載之前,它也需要保持連接。這里就用到了另一個巧妙的庫了: contextlib.closing

  • iter_content:一塊一塊的遍歷要下載的內容
  • iter_lines:一行一行的遍歷要下載的內容

使用上面兩個函數下載大文件可以防止占用過多的內存,因為每次只下載小部分數據。

示例代碼:

r = requests.get(url_file, stream=True)
f = open("file_path", "wb")
for chunk in r.iter_content(chunk_size=512):    # 按照塊的大小讀取
# for chunk in r.iter_lines():    # 按照一行一行的讀取
    if chunk:
        f.write(chunk)

 

更詳細的介紹:

抓取一批URL,並獲取對應URL的<title>標簽中的文字,忽略對應URL網站的封禁問題,這個任務並不是一個特別麻煩的事情。然后實際跑起來,卻發現流量打的很高,超過10Mb/s。

經過排查發現,是因為很多URL,實際是下載鏈接,會觸發文件下載,這些URL對應的html中根本不會包含<title>標簽,那么處理邏輯就很清晰了,先拿到headers,取出Content-Type,判斷是否是
text/html,如果不是,則該Response的body體,就沒有必要讀取了。

這樣的話,只有headers頭被下載了,body中的數據還沒有被下載,這樣就能避免不必要的流量開銷,只有當你使用r.content 的時候,所有body內容才會被下載

實時上還可以使用Response.iter_content() Response.iter_lines()
Response.raw()來自己決定要讀取多少數據

最后要注意的是,使用stream=True以后需要自己執行Response的
關閉操作

好,那么看下我改進后的程序

import logging
import threading
import redis
import requests
from lxml.html import fromstring

r = redis.Redis(host='127.0.0.1', port=6379, db=10)
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                    filename='all.log',
                    filemode='w')
def extract(url):
    logger = logging.getLogger()
    try:
        res = requests.get(url, stream=True, timeout=0.5)
        ctype = res.headers['Content-Type']
        ctype = ctype.lower()
        if ctype.find('text/html') == -1:
            res.close()
            return None

        doc = fromstring(res.content)
        res.close()
        item_list  = doc.xpath('//head/title')
        if item_list:
            res = item_list[0].text_content()
            res = unicode(res)
            logger.info('title = %s', res)
            return res
    except:
        return None
    return None

經過測試,帶寬開銷確實大幅下降了。為requests點個贊,設計者想的太周到了,既允許從hign level去使用它,也可以回到low level去精細化的管理控制連接。

默認情況下requests對URL的訪問是阻塞式的,可以通過使用
1)grequests
2)requests-futures
來實現非阻塞式的訪問

 

 

參考連接:

 nul1 | https://www.cnblogs.com/nul1/p/9172068.html

 

萌叔 | http://vearne.cc/archives/120

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM