如何检查urllib.urlretrieve是否能够使用python到达主机?

时间:2018-08-22 19:10:41

标签: python python-2.7 urllib

我正在尝试从imgnet链接中收集图像并将其保存在文件夹中。 使用urllib.urlretrieve,直到知道它工作得很好。 主要问题是何时该功能尝试访问DNS无法解析的主机。 我的链接是:http://www.fuminnaosu.com/image/person/kitamura.jpg

每个DNS无法解析时(可以删除),但仍在列表中。 Try&Except目前无法在我的项目中使用,是否有任何方法可以通过并继续收集而无需使用Try&Except? 我的错误是:

  File "C:\Anaconda2\lib\socket.py", line 557, in create_connection
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
IOError: [Errno socket error] [Errno 11001] getaddrinfo failed

我的代码:

import cv2
import numpy as np
import os
import urllib

def get_images_to_dir():
    images_list_lnk = 'http://image-net.org/api/text/imagenet.synset.geturls?wnid=n09618957'
    images_url = urllib.urlopen(images_list_lnk)
    urls = images_url.read()

    img_typ = 'neg'

    if not os.path.exists(img_typ):
        os.mkdir(img_typ)

    images_counter = 1

    for url in urls.split('\n'):
            img_name = img_typ+'/'+str(images_counter)+'.jpg'
            urllib.urlretrieve(url, img_name)
            img = cv2.imread(img_name, cv2.IMREAD_GRAYSCALE)
            if (img is not None): # If connection success, but no image was found
                img = cv2.resize(img, (100, 100))
                cv2.imwrite(img_name, img)
                images_counter += 1

完整的错误报告:

Traceback (most recent call last):
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2018.1.4\helpers\pydev\pydevd.py", line 1664, in <module>
    main()
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2018.1.4\helpers\pydev\pydevd.py", line 1658, in main
    globals = debugger.run(setup['file'], None, None, is_module)
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2018.1.4\helpers\pydev\pydevd.py", line 1068, in run
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "C:/Users/xdavi/PycharmProjects/Face_and_eyes_detect/get-image-by-url.py", line 40, in <module>
    get_images_to_dir()
  File "C:/Users/xdavi/PycharmProjects/Face_and_eyes_detect/get-image-by-url.py", line 23, in get_images_to_dir
    urllib.urlretrieve(url, img_name)
  File "C:\Anaconda2\lib\urllib.py", line 98, in urlretrieve
    return opener.retrieve(url, filename, reporthook, data)
  File "C:\Anaconda2\lib\urllib.py", line 245, in retrieve
    fp = self.open(url, data)
  File "C:\Anaconda2\lib\urllib.py", line 213, in open
    return getattr(self, name)(url)
  File "C:\Anaconda2\lib\urllib.py", line 350, in open_http
    h.endheaders(data)
  File "C:\Anaconda2\lib\httplib.py", line 1038, in endheaders
    self._send_output(message_body)
  File "C:\Anaconda2\lib\httplib.py", line 882, in _send_output
    self.send(msg)
  File "C:\Anaconda2\lib\httplib.py", line 844, in send
    self.connect()
  File "C:\Anaconda2\lib\httplib.py", line 821, in connect
    self.timeout, self.source_address)
  File "C:\Anaconda2\lib\socket.py", line 557, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
IOError: [Errno socket error] [Errno 11001] getaddrinfo failed

2 个答案:

答案 0 :(得分:0)

失败,因为地址查找失败。为什么您不能使用try除外块有零意义。

要解决此问题,您可以使用gevent异步greenlets(线程):

from gevent import monkey, spawn as gspawn, joinall
monkey.patch_all()
import cv2
import numpy as np
import os
import urllib

def get_images_to_dir(url):
    img_typ = 'neg'

    if not os.path.exists(img_typ):
        os.mkdir(img_typ)

    img_name = img_typ+'/'+str(images_counter)+'.jpg'
    urllib.urlretrieve(url, img_name)
    img = cv2.imread(img_name, cv2.IMREAD_GRAYSCALE)
    if (img is not None): # If connection success, but no image was found
        img = cv2.resize(img, (100, 100))
        cv2.imwrite(img_name, img)
        images_counter += 1

images_list_lnk = 'http://image-net.org/api/text/imagenet.synset.geturls?wnid=n09618957'
images_url = urllib.urlopen(images_list_lnk)
urls = images_url.read()


jobs = [gspawn(get_images_to_dir,url) for url in urls.split('\n')]

joinall(jobs)

这将使单个作业失败,但继续进行其余的作业,直到尝试了所有作业。您将需要修复代码以正确跟踪图像数量...老实说,我只计算最后的文件数。

答案 1 :(得分:0)

我不明白为什么您不使用try-try,因为要事先进行检查 将重复相同的过程。即 要检查主机是否可以访问,您必须访问它, 而urllib.urlretrieve()会这样做,当它无法访问时会引发异常。 这正是检查网址可用性的函数的方式 应该看起来。

现在,您可以进行半检查,即打开到端口80或443的TCP套接字,查看连接是否成功,然后关闭该套接字。 但是此方法不会检测文件本身是否存在。

所以,您要问的是:

from urllib2 import urlopen
import urllib

def check (url):
    try:
        u = urlopen(url)
        u.close()
        return True
    except:
        return False

URL = "http://adofiueaoiudsfoiu.com/iiiiddddd.img"
if check(URL):
    urllib.urlretrieve(URL, "thefile.img")

您会看到这是多么愚蠢,与服务器联系两次却一无所获,而不仅仅是将urlretrieve()放入try块中。

因此,您应该做的是在try块中使用urllib2.urlopen(),如果成功,则读取数据并保存或执行您需要做的任何事情。 如果不成功,您将忽略所涉及的URL,仅此而已。 我强烈建议您按照上面的说明编写自己的检索函数,并避免使用urllib.urlretrieve()。