Cómo manejar IncompleteRead: en python
python-2.7 web-scraping (7)
Acabo de agregar una excepción más para pasar este problema.
al igual que
try:
r = requests.get(url, timeout=timeout)
except (requests.exceptions.ChunkedEncodingError, requests.ConnectionError) as e:
logging.error("There is a error: %s" % e)
Estoy tratando de obtener algunos datos de un sitio web. Sin embargo me devuelve la incomplete read
. Los datos que estoy tratando de obtener son un gran conjunto de enlaces anidados. Hice algunas investigaciones en línea y descubrí que esto podría deberse a un error del servidor (una codificación de transferencia fragmentada finaliza antes de alcanzar el tamaño esperado). También encontré una solución para arriba en este link
Sin embargo, no estoy seguro de cómo usar esto para mi caso. A continuación se muestra el código en el que estoy trabajando.
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
Por favor ayúdame con esto. Gracias.
Descubrí en mi caso: enviar solicitud HTTP / 1.0, agregar esto, solucionar el problema.
import httplib
httplib.HTTPConnection._http_vsn = 10
httplib.HTTPConnection._http_vsn_str = ''HTTP/1.0''
después de hacer la solicitud:
req = urllib2.Request(url, post, headers)
filedescriptor = urllib2.urlopen(req)
img = filedescriptor.read()
después de volver a http 1.1 con (para conexiones que admiten 1.1):
httplib.HTTPConnection._http_vsn = 11
httplib.HTTPConnection._http_vsn_str = ''HTTP/1.1''
el truco es usar http 1.0 en lugar de que el http / 1.1 http 1.1 predeterminado podría manejar fragmentos, pero por alguna razón el servidor web no lo hace, por lo que hacemos la solicitud en http 1.0
El link que incluyó en su pregunta es simplemente un contenedor que ejecuta la función read () de urllib, que detecta cualquier excepción de lectura incompleta para usted. Si no desea implementar todo este parche, siempre puede lanzar un ciclo de prueba / captura donde lea sus enlaces. Por ejemplo:
try:
page = urllib2.urlopen(urls).read()
except httplib.IncompleteRead, e:
page = e.partial
para python3
try:
page = request.urlopen(urls).read()
except (http.client.IncompleteRead) as e:
page = e.partial
Encontré que mi detector de virus / firewall estaba causando este problema. "Online Shield" parte de AVG.
Lo que funcionó para mí es capturar IncompleteRead como una excepción y recopilar los datos que logró leer en cada iteración colocando esto en un bucle como el siguiente: (Nota, estoy usando Python 3.4.1 y la biblioteca urllib ha cambiado entre 2.7 y 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__())
Probé todas estas soluciones y ninguna de ellas funcionó para mí. En realidad, lo que funcionó es que en lugar de usar urllib, solo usé http.client (Python 3)
conn = http.client.HTTPConnection(''www.google.com'')
conn.request(''GET'', ''/'')
r1 = conn.getresponse()
page = r1.read().decode(''utf-8'')
Esto funciona perfectamente cada vez, mientras que con urllib devolvía una excepción de lectura incompleta cada vez.
Puedes usar requests
lugar de urllib2
. requests
se basan en urllib3
por lo que rara vez tiene algún problema. Ponlo en un bucle para probarlo 3 veces, y será mucho más fuerte. Puedes usarlo de esta manera:
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))