urlretrieve 似乎损坏了图像文件

urlretrieve seems to corrupt image file

我使用 urlretrieve 从网站上抓取图像。除了一个不是那么小的细节外,这很好用。文件不可读。我尝试了几个网站,但结果是一样的。我想知道我是否应该指出它是二进制下载,但在文档中找不到任何提示。在网上搜索,发现了一些与请求库的替代方法,但结果又是一样的。 Windows 照片查看器、Paint 和 Gimp 都报告文件已损坏或无法读取。我很确定我犯了一些愚蠢的错误。任何帮助将不胜感激!

def get_images(url, soup):
    #this makes a list of bs4 element tags
    print 'URL: ', url
    n = 0
    images = [img for img in soup.findAll('img')]

    #compile our unicode list of image links
    image_links = [each.get('src') for each in images]
    for each in image_links:
        n = n + 1
        path = urlparse.urlparse(each).path
        fn = (os.path.split(path)[1]).strip()
        ext = (os.path.splitext(fn)[1]).strip().lower()
        if (fn == '' or ext == ''):
            continue

        fn = os.path.join ("images", fn)

#        print 'From: ', url
        print 'Each> ', each
#        print 'File< ', fn
#        avatar = open(fn, 'wb')
#        avatar.write(requests.get(url).content)
#        avatar.close()
        result = urllib.urlretrieve(url, fn)
        print result

    return n

更新

Jephron 指出了正确的方向,我没有正确地将 url 与图像路径结合起来。他的解决方案通过使用 urlparse.urljoin(url, each) 而像我最初那样使用 os.path.join 来工作,可能会导致 windows 系统上的 url 突然出现反斜杠。很烦人。我添加了相对和绝对 url 路径的测试,最终代码如下所示。

def get_images(url, soup):
    #this makes a list of bs4 element tags
    print ' '
    print 'URL: ', url
    n = 0
    images = [img for img in soup.findAll('img')]

    #compile our unicode list of image links
    image_links = [each.get('src') for each in images]

    for each in image_links:
        path = urlparse.urlparse(each).path
        fn = (os.path.split(path)[1]).strip()
        ext = (os.path.splitext(fn)[1]).strip().lower()
        if (fn == '' or ext == ''):
            continue

        fn = os.path.join ("images", fn)
        if (not (each.startswith ('http:') or each.startswith('https:'))):
            image_link = urlparse.urljoin(url, each)
        else:
            image_link = each

        print 'Found: ', fn

        try:
            urllib.urlretrieve(image_link, fn)
            n = n + 1
        except:
            continue

    return n

但是请注意,3/4 的 .png 文件仍然不可读。我必须找出原因,但可能仍然存在隐藏的障碍。

我 运行 你的代码并查看了它下载的 "image"。原来你保存出来的文件内容实际上是整个HTML站点。尝试在文本编辑器中打开它并亲自查看。

要解决此问题,请注意您传递给 urlretrieve 的参数实际上是您抓取的网页的 url。如果您将图像 url 连接到页面 url,您将获得正确的 url:

def get_images(url, soup):
    #this makes a list of bs4 element tags
    print 'URL: ', url
    n = 0
    images = [img for img in soup.findAll('img')]

    #compile our unicode list of image links
    image_links = [each.get('src') for each in images]
    for each in image_links:
        print "maybe an image"
        print each
        n = n + 1
        path = urlparse.urlparse(each).path
        fn = (os.path.split(path)[1]).strip()
        ext = (os.path.splitext(fn)[1]).strip().lower()
        if (fn == '' or ext == ''):
            continue

        fn = os.path.join ("images", fn)

        print 'Each> ', each

        result = urllib.urlretrieve(os.path.join(url, each), fn)
        print result

    return n