Python:检查JPG图片的URL是否存在

37

1
请通过编辑问题描述来解决以下问题:什么被认为是“存在”?它与“HTTP GET请求成功”有何不同? - bignose
11个回答

53
下面的代码相当于tikiboy的答案,但使用了高级且易于使用的requests库。
import requests

def exists(path):
    r = requests.head(path)
    return r.status_code == requests.codes.ok

print exists('http://www.fakedomain.com/fakeImage.jpg')
requests.codes.ok 等于 200,所以如果你愿意,可以替换为确切的状态码。
如果服务器没有响应,requests.head 可能会抛出 exception 异常,因此您可能需要添加 try-except 结构。
另外,如果您想包括代码 301302,考虑到使用 Linked Data 中表示资源的 URI,尤其是如果您要 dereference URIs。URI 可能代表一个人,但您无法下载一个人,因此服务器将重定向您到一个页面,该页面使用 303 redirect 描述此人。

这个答案看起来是现在最简单和最正常的方法。请参阅https://dev59.com/1HI-5IYBdhLWcg3wF0Qc - brita_
与其他答案相反,在Python 3.5中完美运行。 - Eskapp
根据参考资料,应该查找以下代码:[ 301, 302, 303, 307, 308, 200 ] - Gokul

35
>>> import httplib
>>>
>>> def exists(site, path):
...     conn = httplib.HTTPConnection(site)
...     conn.request('HEAD', path)
...     response = conn.getresponse()
...     conn.close()
...     return response.status == 200
...
>>> exists('http://www.fakedomain.com', '/fakeImage.jpg')
False
如果状态码不是200,那么该URL上的资源不存在。这并不意味着该资源已经完全消失。如果服务器返回301或302,则表示该资源仍然存在,但位于不同的URL上。要更改函数以处理此情况,只需将状态检查行更改为return response.status in (200, 301, 302)

2
+1,虽然我想在调用conn.request时使用HEAD而不是GET可能更有效率,因为你只是检查它是否存在。 - Daniel Roseman
如果出现类似以下错误:gaierror: [Errno 8] nodename nor servname provided, or not known,请确保您的'site'值不包括 http://ftp:// 等内容。相反,看起来 httplib 会尝试推导出正确的协议或需要指定适当的端口号(参见下面的附加注释)。 - bluebinary
1
此外,如果您收到错误消息 “InvalidURL: nonnumeric port: '//www.fakedomain.com'”,请确保将适当的端口号添加到您的“site” URL中。在我的情况下,这意味着将 http://www.fakedomain.com 更改为 www.fakedomain.com:80,从而解决了此问题。事实上,在查看python.org上httplib文档时,我注意到列出的示例排除了URL中的协议定义:http://docs.python.org/2/library/httplib.html - bluebinary
点击这里查看一个比较不同库的链接:https://dev59.com/1HI-5IYBdhLWcg3wF0Qc。Requests似乎是最受欢迎的选择。 - brita_
它适用于此网址http://www.hdwallpapers4ipad.com/_ph/13/426699792.jpg吗?我发现他们可以将其添加为.jpg而实际上并不是图像。 - Shane
显示剩余2条评论

7
感谢大家的回复,最终我使用了以下方法:
try:
  f = urllib2.urlopen(urllib2.Request(url))
  deadLinkFound = False
except:
  deadLinkFound = True

简短而有力。我自己使用这个方法作为我的URL字符串(大约5000个)是完整的URI——我不想太详细了。我还能假设我会收到404而不是重定向。不确定这会在重定向时有效。 - Ben Keating
1
甚至在URL错误以及301、302、303错误时也会返回True。 - Yugal Jindle

4
看起来 http://www.fakedomain.com/fakeImage.jpg 自动重定向到 http://www.fakedomain.com/index.html,没有任何错误返回给用户。
301和302响应的重定向是自动完成的,不会向用户返回任何响应。
请查看HTTPRedirectHandler,您可能需要对其进行子类化以处理此问题。
以下是Dive Into Python中的一个示例: http://diveintopython3.ep.io/http-web-services.html#redirects

3
我认为fakedomain.com只是用作示例的名称,实际上你不需要亲自访问它。:-) - Young
1
@SpawnCxy,起初我也是这么想的,但当我访问那个URL时,fakeImage.jpg并不存在,而且被重定向到index.html,所以我认为它不仅仅是一个例子。 - YOU

4
当文件位于FTP服务器(ftp://url.com/file)时,之前的答案存在问题。以下代码适用于文件位于FTP、HTTP或HTTPS时:
import urllib2

def file_exists(url):
    request = urllib2.Request(url)
    request.get_method = lambda : 'HEAD'
    try:
        response = urllib2.urlopen(request)
        return True
    except:
        return False

我之前尝试了所有的答案,但是当我输入错误的文件URL时,没有一个能够返回False。不过这个答案非常好用! - Darkhydro
有没有使用urllib3完成相同操作的方法? - MehmedB
不完全像这样,因为urllib3需要一些更改 - XavierCLL

2

使用mechanize试试:

import mechanize
br = mechanize.Browser()
br.set_handle_redirect(False)
try:
 br.open_novisit('http://www.fakedomain.com/fakeImage.jpg')
 print 'OK'
except:
 print 'KO'

https://kite.com/python/docs/mechanize.Browser.open_novisit说它不发送响应 - 它必须发送一个响应,对吗? - Areza

1
这可能足够好,以查看文件的URL是否存在。
import urllib
if urllib.urlopen('http://www.fakedomain.com/fakeImage.jpg').code == 200:
  print 'File exists'

0
在Python 3.6.5中:
import http.client

def exists(site, path):
    connection =  http.client.HTTPConnection(site)
    connection.request('HEAD', path)
    response = connection.getresponse()
    connection.close()
    return response.status == 200

exists("www.fakedomain.com", "/fakeImage.jpg")

在Python 3中,模块httplib已被重命名为http.client
此外,您需要从URL中删除http://https://,因为httplib:视为端口号,而端口号必须是数字。

0

@z3moon的回答很好,但我认为它是针对py 2.x的。对于python 3.x,您可能需要在模块调用中添加request

import urllib
def check_valid_URLs(url) -> bool:
  try:
    if urllib.request.urlopen(url).code == 200:
      return True
    else:
      return False
  except:
    return False

0

Python3

import requests

def url_exists(url):
    """Check if resource exist?"""
    if not url:
        raise ValueError("url is required")
    try:
        resp = requests.head(url)
        return True if resp.status_code == 200 else False
    except Exception as e:
        return False

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接