今天来抓取一下壁纸网站上的一些高清无码图片,并保存在本地。索要抓取的网站是https://unsplash.com/

其实今天这篇不是完全意义上的原创,也是参考了网上的一片文章,原文40行动态爬虫代码搞定N张高清无码壁纸下载

之所以来抓这个图片网站主要是为了学习一下json的基本功能和用法,而且也发现了原文中一些小Bug,而且原文的代码是基于Python2.7的,有一些语法和库的使用跟我用的Python3.5的版本还是有些差别的。

Python版本:3.5.3
今天用到的库有
1.requests:用来获取网页的源代码
2.json:用来解析抓到的json文件
2.re:正则表达式模块,用来匹配特性的字符串
2.time:显示当前时间和对程序进行休眠(感觉无所谓,可有可无)

1
2
3
4
import requests
import json
import re
import time

首先跟往常一样先用Chrome浏览器的工具看一下,从Network中可以看到,这个网站的加载是一个类似于瀑布流的效果,当鼠标不断向下滚动的时候,网页会不断加载图片

图上显示的就是所对应加载的json文件,打开文件看一下,发现文件中包含当前页面中图片的id和下个一页面的网址,我们只要获取到这两个信息就能重复不断地抓取网页上的图片了。

原文里面提到,第一个url是:https://api.unsplash.com/napi/feeds/home
但是我仔细找了半天也没找到这个文件,不过这个链接是有效的,而且确实是第一个页面的链接,那就拿来直接用吧(其实也无所谓,我们可以根据任意一个文件开始来顺次抓取相应的图片,只不过这样就不是我们在网页上看到的第一个图片了,并没有太大的影响)

找到相应文件的url,如图所示,不过需要注意的是文件当中的地址和我们需要的文件地址基本相同,只是地址中间多了一个/napi/


当我们点击网页上某一幅图片的下载按钮的时候网页会跳转到下图的链接,并且发下中间那部分就是图片的id

因此,拿到图片的id之后就可以下载图片了。

分析到此结束,开始写程序!

首先构造url和header

1
2
3
4
5
6
7
8
9
10
11
12
Header = {
'authorization':'Client-ID d69927c7ea5c770fa2ce9a2f1e3589bd896454f7068f689d8e41a25b54fa6042',
'accept-version':'v1',
'Host':'unsplash.com',
'x-unsplash-client':'web',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2986.0 Safari/537.36',
'Referer':'https://unsplash.com/',
'Connection':'keep-alive',
'Accept':'*/*'
}
page_url = 'https://api.unsplash.com/napi/feeds/home'

然后通过url和header得到json文件,并解析文件中的next_page和photo信息

1
2
3
4
html = requests.get(url=page_url,headers=Header)
hjson = json.loads(html.text)
next_page = hjson[u'next_page'] # 获取下一个页面的链接
photos = hjson[u'photos'] # 获取当前页面的图片信息

然后用re模块得到下一个页面的链接,然后可以通过匹配的字符串构造出下一个页面的链接,并用于下一个页面的抓取。

得到photos之后可以用过循环依次获取每一张图片的链接地址,并将得到图片保存在本地,这些和上次抓取LOFTER上图片的方法基本上是相似的所以就不详细介绍了,看了代码应该就都懂了

1
2
3
4
5
6
7
8
9
for each in photos:
print(time.strftime('%X'),'正在保存第'+str(cnt)+'张图片...')
bianhao = each['id']
pic = requests.get('https://unsplash.com/photos/'+bianhao+'/download?force=true')
file = open('./pic/' +str(cnt) +'.jpg', 'wb')
file.write(pic.content)
file.close()
cnt += 1
time.sleep(5)

cnt同样是用来做计数和相应的文件名的。
time.strftime(‘%X’)是显示当前的时间,主要是用来查看程序运行的时间以及保存每一幅图片所需要的时间,’%X’为显示格式-只显示小时分钟和秒
每一次循环之后让程序暂定5秒钟,后来发现好像没什么用,本来图片下载就挺慢的了,再加一个延时就更慢了。。。

如果有地方不太了解,可以把相应的参数打印出来看一下程序运行的过程

这样就实现了一个页面的图片的抓取与保存,并别我们也从当前的文件中获取了下一个页面文件的链接,通过循环就可以实现多个页面图片的抓取与保存


我尝试抓了5个页面的图片,一共花了大约30分钟,因为图片比较大,下载了49张图片一共约500M,平均每张图片10M左右