2013-01-21 12 views
13

Próbuję pobrać niektóre dane ze strony internetowej. Jednak zwraca mi incomplete read. Dane, które próbuję uzyskać, to ogromny zestaw zagnieżdżonych linków. Zrobiłem kilka badań w trybie online i odkryłem, że może to być spowodowane błędem serwera (kodowanie kończące transfer przed osiągnięciem oczekiwanego rozmiaru). Również znalazłem obejście dla powyższego na tym linkJak obsługiwać metodę IncompleteRead: w pythonie

Jednak nie jestem pewien, jak korzystać z tego w moim przypadku. Poniżej znajduje się kod pracuję nad

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 

Proszę mi pomóc z this.Thanks

+0

Zwykle po otrzymaniu błędu wypróbowuję inną prośbę i zawsze się to udaje. Może 100 razy na 100 prób. – Blaszard

Odpowiedz

13

link ty zawarte w pytaniu jest po prostu otoki, który wykonuje urllib jest funkcja(), która łapie każdą niepełną Odczyt Odczyt wyjątki dla ciebie. Jeśli nie chcesz zaimplementować tej całej poprawki, zawsze możesz po prostu wrzucić pętlę try/catch, w której czytasz swoje linki. Na przykład:

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

dla python3

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

i to nie działa w python3, żadnych sugestii? –

6

dowiem się w moim przypadku: wysyłanie HTTP/1.0 prośbę, dodając to, aby rozwiązać problem.

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

po robię żądanie:

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

po tym, jak z powrotem do protokołu HTTP 1.1 z (dla połączeń, które obsługują 1.1):

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

Sztuką jest wykorzystanie protokołu HTTP 1.0 zamiast domyślnie http/1.1 http 1.1 może obsługiwać porcje, ale z jakiegoś powodu serwer WWW nie, więc robimy żądanie w http 1.0

+1

@ SSérgio, mając ten sam problem podczas używania 'urllib2.urlopen (url) .read()', Ale powyższy kod rozwiązał to. Czy możesz to wyjaśnić? – fledgling

1

To, co zadziałało, polega na przechwytywaniu IncompleteRead jako wyjątkowi i zbieraniu danych, które udało się odczytać w każdej iteracji, poprzez umieszczenie tego w pętli jak poniżej: (Uwaga, używam Pythona 3.4.1 i biblioteka urllib zmieniła się z 2.7 i 3.4)

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__()) 
0

Znalazłem, że mój wykrywacz wirusów/zapora sieciowa powodował ten problem. "Online Shield" część AVG.

0

Można użyć requests zamiast urllib2. requests jest oparty na urllib3, więc rzadko ma problem. Włóż go w pętlę, aby wypróbować 3 razy, i będzie znacznie silniejszy. Możesz go użyć w następujący sposób:

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)) 
0

Próbowałem wszystkich tych rozwiązań i żaden z nich nie działał dla mnie. Właściwie, co nie działa to zamiast używać urllib, po prostu stosować http.client (Python 3)

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

To działa idealnie za każdym razem, podczas gdy z urllib było zwrócenie incompleteread wyjątek za każdym razem.

+0

To nie działa zawsze, wygląda na to, że rozwiązanie jest dość stare. Czy możesz pomóc w nowym rozwiązaniu dla Python3 –

0

Dodałem tylko wyjątek, aby przekazać ten problem.
jak

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

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

To głównie dzieje się, gdy strona czytasz dane ze jest przeciążony, aby rozwiązać ten złapać błąd i ponowić Twoja prośba again.This pracował dla mnie.

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

    except (requests.exceptions.ChunkedEncodingError) as e: 
     r=request.get(url,timeout=timeout) 
Powiązane problemy