在网页上抓取一个 jpg 文件,然后使用 python 保存它

Scrape a jpg file on webpage, then saving it using python

好的,我正在尝试从 Gucci 网站上抓取 jpg 图片。以此为例。

http://www.gucci.com/images/ecommerce/styles_new/201501/web_full/277520_F4CYG_4080_001_web_full_new_theme.jpg

我试过urllib.urlretrieve,但没用,因为 Gucci 屏蔽了这个功能。所以我想用requests来抓取图片的源代码,然后写入一个.jpg文件。

image = requests.get("http://www.gucci.com/images/ecommerce/styles_new/201501/web_full/277520_F4CYG_4080_001_web_full_new_theme.jpg").text.encode('utf-8')

我对它进行了编码,因为如果我不这样做,它会一直告诉我 gbk 无法对字符串进行编码。

然后:

with open('1.jpg', 'wb') as f:
    f.write(image)

看起来不错吧?但结果是——无法打开 jpg 文件。没有图像! Windows 告诉我 jpg 文件已损坏。

可能是什么问题?

  1. 我在想,可能是我在抓图的时候漏掉了一些信息,或者抓错了一些字符。但是我怎样才能找出是哪一个呢?

  2. 我在想,也许一些信息通过编码丢失了。但是如果我不编码,我连打印都无法打印,更不用说写入文件了。

可能会出什么问题?

我不确定您使用 encode 的目的。您不是在处理文本,而是在处理图像。您需要以二进制数据而不是文本形式访问响应,并使用图像处理函数而不是文本函数。试试这个:

from PIL import Image
from io import BytesIO
import requests

response = requests.get("http://www.gucci.com/images/ecommerce/styles_new/201501/web_full/277520_F4CYG_4080_001_web_full_new_theme.jpg")
bytes = BytesIO(response.content)
image = Image.open(bytes)
image.save("1.jpg")

请注意使用 response.content 而不是 response.text。您需要安装 PIL 或 Pillow 才能使用 Image 模块。 BytesIO 包含在 Python 3.

或者您可以直接将数据保存到磁盘而不看里面的内容:

import requests
response = requests.get("http://www.gucci.com/images/ecommerce/styles_new/201501/web_full/277520_F4CYG_4080_001_web_full_new_theme.jpg")
with open('1.jpg','wb') as f:
    f.write(response.content)

JPEG 文件不是文本,它是二进制数据。所以你需要使用request.content属性来访问它。

下面的代码还包含一个 get_headers() 函数,当您浏览网站时,它会很方便。

import requests

def get_headers(url):
    resp = requests.head(url)
    print("Status: %d" % resp.status_code)
    resp.raise_for_status()
    for t in resp.headers.items():
        print('%-16s : %s' % t)

def download(url, fname):
    ''' Download url to fname '''
    print("Downloading '%s' to '%s'" % (url, fname))
    resp = requests.get(url)
    resp.raise_for_status()
    with open(fname, 'wb') as f:
        f.write(resp.content)

def main():
    site = 'http://www.gucci.com/images/ecommerce/styles_new/201501/web_full/'
    basename = '277520_F4CYG_4080_001_web_full_new_theme.jpg'
    url = site + basename
    fname = 'qtest.jpg'

    try:
        #get_headers(url)
        download(url, fname)
    except requests.exceptions.HTTPError as e:
        print("%s '%s'" % (e, url))

if __name__ == '__main__':
    main()

我们调用 .raise_for_status() 方法,以便 get_headers()download() 在出现问题时引发异常;我们在 main() 中捕获异常并打印相关信息。