【爬虫军火库】下载保存图片(文件)

时间:2022-05-07
本文章向大家介绍【爬虫军火库】下载保存图片(文件),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

今天开始开一个新坑,暂且叫做【爬虫军火库】吧。以前一直想系统地写些东西,最终大都未能成文,想来我不适合发宏愿立长志,还是一步一个脚印地写点零碎的东西。有关爬虫,以后会写很多东西,写完以后再进行梳理好了。

之所以要写军火库,是因为在写爬虫的过程中,遇到过很多重复性的工作。即便是Python的社区环境已经提供了很多很方便的第三方库,在实际操作中也难免需要根据不同情况做很多具体的分析。所以接下来要写的这个系列,会很像一个utils,记录一些小而实用、可复用的代码段,有些时候不会去关注前因后果,只是简简单单地聚焦在一个很小的功能上。仅此而已。

是为短序。

军火库这个系列没有严格顺序,想到什么、遇到什么,就会及时地写下来。

昨天在后台收到一个提问:

于是今天我们先来写一下下载、保存图片(文件)的方法。

假设现在已有一个图片(文件)的网址,如何保存到本地。

1、最简便的办法,使用urllib.request.urlretrieve

用法:urlretrieve(url, filename=None, reporthook=None, data=None)

示例1:http://placekitten.com/500/600 这是一个提供猫片的网站,你只需要修改之后的两个数字就可以获取相应宽高比的小猫图片。

现在要将这张图片下载到本地:

import urllib.request
url = 'http://placekitten.com/500/600'
urllib.request.urlretrieve(url, 'cat_img.jpg')

示例2:下载新浪财经年报PDF 如http://vip.stock.finance.sina.com.cn/corp/view/vCB_AllBulletinDetail.php?stockid=000048&id=712408

import urllib.request
url = 'http://file.finance.sina.com.cn/211.154.219.97:9494/MRGG/CNSESZ_STOCK/2011/2011-4/2011-04-26/712408.PDF'
urllib.request.urlretrieve(url, '712408.pdf')

2、请求获取bytes后自己建文件存

还是前面的示例1,可以写成:

import requests
url = 'http://placekitten.com/500/600'
r = requests.get(url).content #这里也可以用urllib.request.urlopen()方法
f = open('cat_img.jpg', 'wb')
f.write(r)
f.close()

这样写自然是不如之前的一行代码解决问题来的方便,但是这样有一个好处,就是方便解决网络请求的问题。尤其是使用requests库时,无论是添加headers还是添加proxies,都十分方便。

举个栗子。各家爬虫文章最喜欢写的入门网站,妹子图(排第二的可能是煎蛋?),现在新加了反盗链的措施,说白了就是要验证请求头中的Referer字段。这是如果直接用urlretrieve就会获取到这样的结果:

于是我们需要这么来做:

import requests
headers = {'Referer': 'http://www.mzitu.com/'}
url = 'http://i.meizitu.net/2015/12/05m01.jpg'
r = requests.get(url, headers=headers).content
f = open('mzitu.jpg', 'wb')
f.write(r)
f.close()

3、解决urlretrieve添加headers的问题

前面的方法2中说到,urlretrieve不方便添加headers,但是并不是不能添加。如果一定要用的话,就需要构建opener。

import urllib.request
url = 'http://i.meizitu.net/2015/12/05m01.jpg'
opener=urllib.request.build_opener()
opener.addheaders = [('Referer', 'http://www.mzitu.com/')]
urllib.request.install_opener(opener)
urllib.request.urlretrieve(url, 'mzitu.jpg')

一般来说大概就是这些问题了。常用到的可以写成函数,以便以后调用。还有一个问题就是,在具体拼接储存路径时经常需要用到字符串的split方法,结合os.getcwd(),os.mkdir(),os.chdir()等。

最后回到最初的问题,为什么加了Referer都没有获取到图片呢?其实是个乌龙,我看了这位朋友的代码,其中有这么一行:

rsp = requests.get(url_real, headers).content

需要注意的是,这么写其实没有把headers添加进去。

我们可以用inspect来查看requests.get()方法所需的参数。

所以在添加headers时一定要写成:

rsp = requests.get(url_real, headers=headers).content

最后插句题外话,后台的自动回复又打开了,图片识别的接口有问题还在调,所以识图功能暂时用不了,会尽快想办法的。