Как мне изменить эту функцию загрузки в Python? - PullRequest
2 голосов
/ 13 января 2011

Прямо сейчас это ненадежно. Gzip, изображения, иногда это не работает.

Как мне изменить эту функцию загрузки, чтобы она могла работать с чем угодно? (Независимо от gzip или любого заголовка?)

Как мне автоматически " Определить ", если это gzip? Я не хочу всегда передавать True / False, как я делаю прямо сейчас.

def download(source_url, g = False, correct_url = True):
    try:
        socket.setdefaulttimeout(10)
        agents = ['Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)','Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1)','Microsoft Internet Explorer/4.0b1 (Windows 95)','Opera/8.00 (Windows NT 5.1; U; en)']
        ree = urllib2.Request(source_url)
        ree.add_header('User-Agent',random.choice(agents))
        ree.add_header('Accept-encoding', 'gzip')
        opener = urllib2.build_opener()
        h = opener.open(ree).read()
        if g:
            compressedstream = StringIO(h)
            gzipper = gzip.GzipFile(fileobj=compressedstream)
            data = gzipper.read()
            return data
        else:
            return h
    except Exception, e:
        return ""

Ответы [ 3 ]

4 голосов
/ 13 января 2011

Проверьте заголовок Content-Encoding:

import urllib2
import socket
import random
import StringIO
import gzip

def download(source_url):
    try:
        socket.setdefaulttimeout(10)
        agents = ['Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)','Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1)','Microsoft Internet Explorer/4.0b1 (Windows 95)','Opera/8.00 (Windows NT 5.1; U; en)']
        ree = urllib2.Request(source_url)
        ree.add_header('User-Agent',random.choice(agents))
        ree.add_header('Accept-encoding', 'gzip')
        opener = urllib2.build_opener()
        response = opener.open(ree)
        encoding=response.headers.getheader('Content-Encoding')
        content = response.read()
        if encoding and 'gzip' in encoding:
            compressedstream = StringIO.StringIO(content)
            gzipper = gzip.GzipFile(fileobj=compressedstream)
            data = gzipper.read()
            return data
        else:
            return content
    except urllib2.URLError as e:
        return ""

data=download('http://api.stackoverflow.com/1.0/questions/3708418?type=jsontext')
print(data)

Если вы имеете дело с сервером, который не сообщает о кодировке содержимого как gzip, то вы можете быть более агрессивными, просто try сначала введя:

def download(source_url):
    try:
        socket.setdefaulttimeout(10)
        agents = ['Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)','Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1)','Microsoft Internet Explorer/4.0b1 (Windows 95)','Opera/8.00 (Windows NT 5.1; U; en)']
        ree = urllib2.Request(source_url)
        ree.add_header('User-Agent',random.choice(agents))
        ree.add_header('Accept-encoding', 'gzip')
        opener = urllib2.build_opener()
        response = opener.open(ree)
        content = response.read()
        compressedstream = StringIO.StringIO(content)
        gzipper = gzip.GzipFile(fileobj=compressedstream)
        try:
            data = gzipper.read()
        except IOError:
            data = content
        return data        
    except urllib2.URLError as e:
        return ""
1 голос
/ 13 января 2011
import urllib2
import StringIO
import gzip

req = urllib2.Request('http:/foo/')
h = urllib2.urlopen(req)
data = resp.read()
if 'gzip' in resp.headers['Content-Encoding']:
    compressedstream = StringIO(h)
    gzipper = gzip.GzipFile(fileobj=compressedstream)
    data = gzipper.read()

# etc...
1 голос
/ 13 января 2011

Чтобы определить, какой тип данных вы загружаете, вы должны заменить h = opener.open(ree).read() на h = opener.open(ree).

Теперь через h у вас есть объект ответа.Вы можете анализировать заголовки, используя объект h.headers (dict-like).Особенно вас заинтересуют заголовки «тип контента» и «кодировка контента».Вы можете определить отправляемый контент, проанализировав его.

def download(source_url, correct_url = True):
    try:
        socket.setdefaulttimeout(10)
        agents = ['Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)','Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1)','Microsoft Internet Explorer/4.0b1 (Windows 95)','Opera/8.00 (Windows NT 5.1; U; en)']
        ree = urllib2.Request(source_url)
        ree.add_header('User-Agent',random.choice(agents))
        ree.add_header('Accept-encoding', 'gzip')
        opener = urllib2.build_opener()
        h = opener.open(ree)
        if 'gzip' in h.headers.get('content-type', '') or
           'gzip' in h.headers.get('content-encoding', ''):
            compressedstream = StringIO(h.read())
            gzipper = gzip.GzipFile(fileobj=compressedstream)
            data = gzipper.read()
            return data
        else:
            return h.read()
    except Exception, e:
        return ""
...