【问题标题】:How to handle IncompleteRead: in python如何处理 IncompleteRead:在 python 中
【发布时间】:2013-01-04 17:15:40
【问题描述】:

我正在尝试从网站获取一些数据。但是它返回给我incomplete read。我要获取的数据是大量嵌套链接。我在网上做了一些研究,发现这可能是由于服务器错误(之前完成的分块传输编码 达到预期大小)。我还在 link

上找到了上述解决方法

但是,我不确定如何将其用于我的情况。以下是我正在处理的代码

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

请帮帮我。谢谢

【问题讨论】:

  • 通常,在我收到错误后我尝试另一个请求,它总是成功。 100 次试验中可能有 100 次。

标签: python python-2.7 web-scraping beautifulsoup mechanize


【解决方案1】:

您在问题中包含的link 只是一个执行 urllib 的 read() 函数的包装器,它会为您捕获任何不完整的读取异常。如果你不想实现整个补丁,你总是可以在读取链接的地方抛出一个 try/catch 循环。例如:

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

对于python3

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

【讨论】:

  • 这不是一个解决方案,它只是用 try catch 来扭转它
【解决方案2】:

请注意,此答案仅适用于 Python 2(于 2013 年发布)

我发现:发送 HTTP/1.0 请求,添加这个,解决问题。

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

在我提出请求后:

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

在我回到 http 1.1 之后(对于支持 1.1 的连接):

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

诀窍是使用 http 1.0 而不是默认的 http/1.1 http 1.1 可以处理块,但由于某种原因 webserver 不能,所以我们在 http 1.0 中执行请求

对于 Python3,它会告诉你

ModuleNotFoundError: 没有名为“httplib”的模块

然后尝试使用 http.client 模块就可以解决问题了

import http.client as http
http.HTTPConnection._http_vsn = 10
http.HTTPConnection._http_vsn_str = 'HTTP/1.0'


【讨论】:

  • @SSérgio ,在使用urllib2.urlopen(url).read() 时遇到同样的问题,但上面的代码解决了这个问题。你能解释一下吗?
  • webserver 不能正确处理块,因为它是旧的或者是微软的,或者它的连接速度很慢......
【解决方案3】:

对我有用的是捕获 IncompleteRead 作为异常并通过将其放入如下循环中来收集您在每次迭代中设法读取的数据:(注意,我使用的是 Python 3.4.1 并且 urllib 库在2.7 和 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__())

【讨论】:

    【解决方案4】:

    我发现我的病毒检测器/防火墙导致了这个问题。 AVG 的“Online Shield”部分。

    【讨论】:

      【解决方案5】:

      您可以使用requests 代替urllib2requests 基于urllib3 所以它很少有任何问题。把它放在一个循环中尝试3次,它会强大得多。你可以这样使用它:

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

      【讨论】:

      • 我还添加了一个重试循环,但是每当我遇到IncompleteRead 异常时,它就会跳出我的while 循环并且不会再进行尝试。有什么想法吗?
      【解决方案6】:

      我尝试了所有这些解决方案,但没有一个对我有用。实际上,起作用的不是使用 urllib,而是使用 http.client (Python 3)

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

      这每次都能完美运行,而 urllib 每次都返回一个不完整的读取异常。

      【讨论】:

      • 这并不总是有效,看起来解决方案已经很老了。能否请您帮助 Python3 的新解决方案
      【解决方案7】:

      我只是添加了一个异常来解决这个问题。
      就像

      try:
          r = requests.get(url, timeout=timeout)
      
      except (requests.exceptions.ChunkedEncodingError, requests.ConnectionError) as e:
          logging.error("There is a error: %s" % e)
      

      【讨论】:

        【解决方案8】:

        python3 仅供参考

        from urllib import request
        import http.client
        import os
        url = 'http://shop.o2.co.uk/mobile_phones/Pay_Monthly/smartphone/all_brand'
        try:    
            response = request.urlopen(url)                                       
            file = response.read()  
        except http.client.IncompleteRead as e:
            file = e.partial
        except Exception as result:
            print("Unkonw error" + str(result))
            return
        
        #   save  file 
            with open(file_path, 'wb') as f:
                 print("save -> %s " % file_path)
                 f.write(file)
        

        【讨论】:

          猜你喜欢
          • 2016-11-25
          • 2015-09-12
          • 2012-08-09
          • 1970-01-01
          • 1970-01-01
          • 2011-05-09
          • 2014-02-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多