【问题标题】:Check If Image URL Leads To Real Image in Python检查图像 URL 是否导致 Python 中的真实图像
【发布时间】:2019-01-16 08:17:43
【问题描述】:

所以我正在构建一个 Python 脚本来从 url 列表中下载图像。该脚本在一定程度上可以工作。我不希望它下载网址不存在的图像。我处理了一些使用状态代码的图像,但仍然得到坏图像。 我仍然得到很多我不想要的图像。比如这些:

这是我的代码:

import os
import requests
import shutil
import random
import urllib.request

def sendRequest(url):
    try:
        page = requests.get(url, stream = True, timeout = 1)

    except Exception:
        print('error exception')
        pass

    else:
        #HERE IS WHERE I DO THE STATUS CODE
        print(page.status_code)
        if (page.status_code == 200):
            return page

    return False

def downloadImage(imageUrl: str, filePath: str):
    img = sendRequest(imageUrl)

    if (img == False):
        return False

    with open(filePath, "wb") as f:
        img.raw.decode_content = True

        try:
            shutil.copyfileobj(img.raw, f)
        except Exception:
            return False

    return True

os.chdir('/Users/nikolasioannou/Desktop')
os.mkdir('folder')

fileURL = 'http://www.image-net.org/api/text/imagenet.synset.geturls?wnid=n04122825'
data = urllib.request.urlopen(fileURL)

output_directory = '/Users/nikolasioannou/Desktop/folder'

line_count = 0

for line in data:
    img_name = str(random.randrange(0, 10000)) + '.jpg'
    image_path = os.path.join(output_directory, img_name)
    downloadImage(line.decode('utf-8'), image_path)
    line_count = line_count + 1
#print(line_count)

感谢您的宝贵时间。任何想法都表示赞赏。

真诚地, 尼古拉斯

【问题讨论】:

  • 您可以检查 jpeg 或 png 标头和魔术序列
  • 感谢您的快速回复!抱歉,我对 Python 还很陌生,我该怎么做? @juliusmh
  • 问题是你得到的不是像 HTML 页面那样的图像,还是你得到无用的占位符图像?

标签: python exception error-handling httprequest urlrequest


【解决方案1】:

您可以检查 jpeg 或 png 标头及其各自的魔术序列,这始终是有效图像的一个很好的指标。看this这么问。

您可以查看文件签名(又名幻数)here。然后你只需要检查response.raw的第一个n字节

我稍微修改了您的 sendRequest/download 函数,您应该能够硬编码更多有效的图像文件扩展名,而不仅仅是 JPG 幻数。我终于测试了代码并且它正在工作(在我的机器上)。仅保存有效的 JPG 图像。请注意,我删除了 stream=True 标志,因为图像非常小,您不需要流。并且节省变得不那么神秘了。看看:

def sendRequest(url):
    try:
        page = requests.get(url)

    except Exception as e:
        print("error:", e)
        return False

    # check status code
    if (page.status_code != 200):
        return False

    return page

def downloadImage(imageUrl: str, filePath: str):
    img = sendRequest(imageUrl)

    if (img == False):
        return False

    if not img.content[:4] == b'\xff\xd8\xff\xe0': return False

    with open(filePath, "wb") as f:
        f.write(img.content)

    return True

您也可以尝试使用 Pillow 和 BytesIO 打开图像

>>> from PIL import Image
>>> from io import BytesIO

>>> i = Image.open(BytesIO(img.content))

并查看它是否引发错误。但是第一个解决方案似乎更轻量级 - 你不应该在那里得到任何误报。您还可以检查 im.content 中的字符串 "<html>",如果找到则中止 - 这非常简单,也可能非常有效。

【讨论】:

  • 如何检查标题及其各自的魔术序列?我查看了链接的问题,并没有明白多少。感谢您的帮助。
  • 我想我困惑的地方是文件签名是做什么的?他们会告诉我关于图像文件的什么信息,我如何知道应该寻找哪个文件签名来查找带有错误 url 的图像?
  • 基本上你不知道服务器响应什么或者 url 不再存在等等。因此,像 JPEG 或 PNG 图像这样的文件有一个恒定定义的字节序列,因此应用程序可以检测文件类型而无需依赖扩展名。您的问题与网址无关。你有一堆你刚刚下载的字节,你想检查这束字节是否是一个图像。我更新了我的签名检查问题。
  • 哦,我好像,@juliusmh。感谢您的解释。我来看看答案
  • 很高兴它有帮助,如果您需要其他帮助,请发表评论。这听起来像是一个常见的问题,也许有一个库,或者您可以将这些签名与检查功能捆绑到一个小库中,这也是一个好习惯!还有另一种方法可以检查字节是否为有效图像:您可以尝试使用 Pillow 和 BytesIO 加载图像
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-10
  • 1970-01-01
  • 2019-09-04
  • 2016-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多