今天工做上有個需求,數據庫有個表有將近3萬條url記錄,每條記錄都是一個圖片,我須要請求他們拿到每一個圖片存到本地。一開始我是這麼寫的(僞代碼):html
import requests for url in urls: try: r = requests.get(url).content save_image(r) except Exception, e: print str(e)
然而在服務器上運行時, 會發現每隔一些請求會報相似下面的錯誤:python
HTTPConnectionPool(host='wx.qlogo.cn', port=80): Max retries exceeded with url: /mmopen/aTVWntpJLCAr2pichIUx8XMevb3SEbktTuLkxJLHWVTwGfkprKZ7rkEYDrKRr5icyDGIvU4iasoyRrqsffbe3UUQXT5EfMEbYKg/0 (Caused by <class 'socket.error'>: [Errno 104] Connection reset by peer)
這讓我想起了以前經過hacker news api 在本身電腦上請求一條一條數據時,爲了加快處理速度,採用多進程的方式請求接口,也會出現這樣的錯誤。以前我是作了錯誤記錄直接pass了,此次狀況下由於須要請求全部圖片,在google查了相關緣由,大概是由於我頻繁請求,服務器關閉了部門請求鏈接。參見這裏, 這裏, 這裏。
因此我粗暴地這麼作,還真解決了:git
import requests for url in urls: for i in range(10): try: r = requests.get(url).content except Exception, e: if i >= 9: do_some_log() else: time.sleep(0.5) else: time.sleep(0.1) break save_image(r)
代碼很簡陋,但能夠說明大致解決方案,在每一個請求間增長延時能夠減小大部分請求拒絕,但仍是存在一些請求被拒絕的,因此在那部分請求被拒絕後,發起重試,在被拒10次後才善罷甘休(記錄到日誌)。在實際的請求中,加了0.1s的延遲被拒絕的狀況明顯少了不少,被拒絕重試的次數最多爲3次,最後成功地取下了所有圖片。github