簡體   English   中英

從urllib2遷移到pycurl

[英]migrate from urllib2 to pycurl

我有一個使用urllib2的代碼片段,如下所示。我正在嘗試將其轉換為pycurl,以從pycurl代理支持中受益。 pycurl的轉換后的代碼顯示在原始代碼之后。.我想知道如何將urllib.urlopen(req).read()更改為pycurl中的類似內容..也許使用諸如strinIO之類的東西?

urllib2代碼:

URL = 'URL'
UN = 'UN'
PWD = 'PWD'
HEADERS = { 'Accept': 'application/json',
            'Connection': 'Keep-Alive',
            'Accept-Encoding' : 'gzip',
            'Authorization' : 'Basic %s' % base64.encodestring('%s:%s' % (UN, PWD))  }
req = urllib2.Request(URL, headers=HEADERS)
    response = urllib2.urlopen(req, timeout=(KEEP_ALIVE))
    # header -  print response.info()
    decompressor = zlib.decompressobj(16+zlib.MAX_WBITS)
    remainder = ''
    while True:
        tmp = decompressor.decompress(response.read(CHUNKSIZE))

具有代理支持的pycurl轉換:

URL = 'URL'
UN = 'UN'
PWD = 'PWD'
HEADERS = [ 'Accept : application/json',
            'Connection : Keep-Alive',
            'Accept-Encoding : gzip',
            'Authorization : Basic %s' % base64.encodestring('%s:%s' % (UN, PWD))  ]
req = pycurl.Curl()
    req.setopt(pycurl.CONNECTTIMEOUT,KEEP_ALIVE)
    req.setopt(pycurl.HTTPHEADER, HEADERS)
    req.setopt(pycurl.TIMEOUT, 1+KEEP_ALIVE)
    req.setopt(pycurl.PROXY, 'http://my-proxy')
    req.setopt(pycurl.PROXYPORT, 8080)
    req.setopt(pycurl.PROXYUSERPWD, "proxy_access_user : proxy_access_password")
    req.setopt(pycurl.URL , URL)
    response = req.perform()
    decompressor = zlib.decompressobj(16+zlib.MAX_WBITS)
    remainder = ''
    while True:
        tmp = decompressor.decompress(urllib2.urlopen(req).read(CHUNKSIZE))

提前致謝。

urllib2不同, urllib2返回可用於獲取數據的對象,而curl需要您向其傳遞一個可用於存儲數據的對象。

大多數示例中使用的簡單方法是將文件對象作為WRITEDATA選項傳遞。 您可能認為您可以在此處傳遞StringIO ,如下所示:

# ...
s = StringIO.StringIO()
req.setopt(pycurl.WRITEDATA, s)
req.perform()
data = s.getvalue()

不幸的是,這是行不通的,因為文件對象必須是真實文件(或者至少是具有C級文件描述符的文件),並且StringIO不合格。


您當然可以使用NamedTemporaryFile ,但是如果您希望將文件保留在內存中,或者最好不要將其存儲在內存磁盤上,而只是在運行中進行處理,那將無濟於事。


解決方案是改用WRITEFUNCTION選項:

s = StringIO.StringIO()
req.setopt(pycurl.WRITEFUNCTION, s.write)
req.perform()
data = s.getvalue()

如您所見,您可以根據需要使用StringIO -實際上,這正是pycurlcurl對象文檔pycurl工作–但是,它並沒有比任何其他累積字符串的方式(例如將它們放入其中)真正簡化了太多事情列表和''.join它們連接起來,甚至只是將它們連接到字符串上)。

請注意,我聯系到C級libcurl文檔,而不是pycurl文檔,因為pycurl的文檔基本上只是說:‘FOO做同樣的事情CURLOPT_FOO’(即使差別,喜歡的事實,你WRITEFUNCTION不獲取大小,nmemb和userdata參數)。


如果要動態傳輸數據怎么辦? 只需使用WRITEFUNCTION進行累積和處理。 您不會自己編寫循環,但是curl將在內部循環並推動該過程。 例如:

z = zlib.decompressobj()
s = []
def handle(chunk):
    s.append(z.decompress(chunk))
    return len(chunk)
req.setopt(pycurl.WRITEFUNCTION, handle)
req.perform()
s.append(z.flush())
data = ''.join(s)

curl將針對它檢索到的每個數據塊調用一次函數,因此整個循環發生在該req.perform()調用內。 (它也可能以0字節結尾再次調用它,因此請確保您的回調函數可以處理該問題。我認為z.decompress可以,但是您可能要驗證一下。)

有多種方法可以限制每次寫入的大小,中途中止下載,將標頭作為寫入的一部分而不是單獨獲取等,但是通常您無需進行任何操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM