web-dev-qa-db-fra.com

Comment gérer IncompleteRead: en python

J'essaie d'extraire des données d'un site Web. Cependant il me retourne incomplete read. Les données que j'essaie d'obtenir sont un ensemble énorme de liens imbriqués. J'ai fait des recherches en ligne et j'ai constaté que cela était peut-être dû à une erreur de serveur (l'encodage d'un transfert en bloc se terminant avant Atteignant la taille attendue). J'ai également trouvé une solution de contournement pour ce qui précède link

Cependant, je ne suis pas sûr de savoir comment utiliser cela pour mon cas. Voici le code sur lequel je travaille

br = mechanize.Browser()
br.addheaders = [('User-agent', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1;Trident/5.0)')]
urls = "http://shop.o2.co.uk/mobile_phones/Pay_Monthly/smartphone/all_brands"
page = urllib2.urlopen(urls).read()
soup = BeautifulSoup(page)
links = soup.findAll('img',url=True)

for tag in links:
    name = tag['alt']
    tag['url'] = urlparse.urljoin(urls, tag['url'])
    r = br.open(tag['url'])
    page_child = br.response().read()
    soup_child = BeautifulSoup(page_child)
    contracts = [tag_c['value']for tag_c in soup_child.findAll('input', {"name": "tariff-duration"})]
    data_usage = [tag_c['value']for tag_c in soup_child.findAll('input', {"name": "allowance"})]
    print contracts
    print data_usage

S'il vous plaît aidez-moi avec this.Merci

21
user1967046

Le link que vous avez inclus dans votre question est simplement un wrapper qui exécute la fonction read () de urllib, qui intercepte toutes les exceptions de lecture incomplètes. Si vous ne souhaitez pas implémenter tout ce correctif, vous pouvez toujours insérer une boucle try/catch dans laquelle vous lisez vos liens. Par exemple:

try:
    page = urllib2.urlopen(urls).read()
except httplib.IncompleteRead, e:
    page = e.partial

pour python3

try:
    page = request.urlopen(urls).read()
except (http.client.IncompleteRead) as e:
    page = e.partial
18
Kyle

Je découvre dans mon cas: envoyer une requête HTTP/1.0, en ajoutant ceci, corrige le problème.

import httplib
httplib.HTTPConnection._http_vsn = 10
httplib.HTTPConnection._http_vsn_str = 'HTTP/1.0'

après avoir fait la demande: 

req = urllib2.Request(url, post, headers)
filedescriptor = urllib2.urlopen(req)
img = filedescriptor.read()

après mon retour à http 1.1 avec (pour les connexions prenant en charge la version 1.1): 

httplib.HTTPConnection._http_vsn = 11
httplib.HTTPConnection._http_vsn_str = 'HTTP/1.1'

l'astuce consiste à utiliser http 1.0 à la place de la valeur par défaut http/1.1 http 1.1 pourrait gérer des blocs mais, pour une raison quelconque, le serveur Web ne le fait pas. Nous effectuons donc la requête dans http 1.0.

7
Sérgio

Vous pouvez utiliser requests au lieu de urllib2. requests est basé sur urllib3, de sorte qu'il a rarement un problème. Mettez-le en boucle pour l'essayer 3 fois, et ce sera beaucoup plus fort. Vous pouvez l'utiliser de cette façon:

import requests      

msg = None   
for i in [1,2,3]:        
    try:  
        r = requests.get(self.crawling, timeout=30)
        msg = r.text
        if msg: break
    except Exception as e:
        sys.stderr.write('Got error when requesting URL "' + self.crawling + '": ' + str(e) + '\n')
        if i == 3 :
            sys.stderr.write('{0.filename}@{0.lineno}: Failed requesting from URL "{1}" ==> {2}\n'.                       format(inspect.getframeinfo(inspect.currentframe()), self.crawling, e))
            raise e
        time.sleep(10*(i-1))
1
Aminah Nuraini

Ce qui a fonctionné pour moi est de capturer IncompleteRead comme exception et de récolter les données que vous avez réussi à lire à chaque itération en les mettant dans une boucle comme ci-dessous: )

try:
    requestObj = urllib.request.urlopen(url, data)
    responseJSON=""
    while True:
        try:
            responseJSONpart = requestObj.read()
        except http.client.IncompleteRead as icread:
            responseJSON = responseJSON + icread.partial.decode('utf-8')
            continue
        else:
            responseJSON = responseJSON + responseJSONpart.decode('utf-8')
            break

    return json.loads(responseJSON)

except Exception as RESTex:
    print("Exception occurred making REST call: " + RESTex.__str__())
1
gDexter42

J'ai essayé toutes ces solutions et aucune d'entre elles n'a fonctionné pour moi. En fait, ce qui a fonctionné est au lieu d'utiliser urllib, je viens d'utiliser http.client (Python 3)

conn = http.client.HTTPConnection('www.google.com')
conn.request('GET', '/')
r1 = conn.getresponse()
page = r1.read().decode('utf-8')

Cela fonctionne parfaitement à chaque fois, alors qu’urllib renvoyait à chaque fois une exception incomplète.

0
Brian

Je viens d'ajouter une exception pour passer ce problème.
juste comme 

try:
    r = requests.get(url, timeout=timeout)

except (requests.exceptions.ChunkedEncodingError, requests.ConnectionError) as e:
    logging.error("There is a error: %s" % e)
0
KJoker

J'ai constaté que mon détecteur de virus/pare-feu était à l'origine de ce problème. "Bouclier en ligne" fait partie d'AVG.

0
nigel76