简单爬虫实现Unsplash上图片的自动下载

一:环境
---------
操作系统 :       Windows10
Python版本 :  Python 3.6.4
IDE :               Pycharm
所需模块 :       requests,urllib

二:爬取网址
----------
Unsplash : https://unsplash.com/

三:分析过程

----------

要爬取一个网站,我们首先想的就是分析该网页,通过浏览器的查看元素,我们能够很容易的看到该网页的源码,我们随便在一张图片上单击右键,查看该图片在源码中的位置。

在图中,我们可以看到我们所需要的图片所在的节点,这是一个img标签的节点,里面有我们所需要的图片的位置。

我们捋一下思路,显然我们要做的步骤如下1:对网页进行解析  2:提取出图片的路径  3:访问路径进行下载

然而事实并没有这么简单,仔细看看,我们会发现,网页源码中只有为数不多的几个img标签,也就是说,我们只能获取到几张图片的路径,我们要的可是大量的图片,接下来将页面下滑,会发现img标签多了起来,很显然这是一个Ajax[1]动态加载的网站,抓包分析,可以看到响应中的是json[2],在json中我们可以找到11张需要的图片的路径信息。

选定其中一个请求,分析它的参数信息。可以发现,这是一个GET类型的请求,请求网址为https://unsplash.com/napi/photos?page=5&per_page=12&order_by=latest,在这url中,我们看到了 https://unsplash.com/,这个是我们请求网站的网址,那后面的东西是啥?别急,我们接着看,"page=5" 应该是第五页的意思,是个变化的值,"per_page=12" 是个固定的参数,"order_by=latest" 也是个固定的参数,所以捋一下思路,我们只要构造page这个参数,然后用循环遍历每一页,就能获取到所有的json数据了,现在你或许胸有成竹了,以为稳操胜券???

然而,当我们访问图片路径时,貌似并没有得到我们想要的结果,我们看一下http请求,什么?302。。。被重定向了,有点意思,知道了问题所在,该如何解决呢?我们可以给requests.get方法中加一个参数,allow_redirects,这个参数默认为True,我们可以改为allow_redirects=False,不允许其重定向。然后,我们就可以获取到它的真实下载路径。

response=requests.get(url,headers=headers,allow_redirects=False)
photo_url_download = response.headers['Location']

至此,我们算是解决了所有的问题,接下来,我们要开始撸代码了。

四:实际操作

---------

我们先将初始信息写下,这里的初始信息主要是一些url,以及一些headers信息,这在我们后面会用到。

import requests
from urllib.parse import urlencode

#初始信息
NUMBER_OF_PHOTO=100
base_url='https://unsplash.com/napi/photos?'
headers={
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0',
    'X-Requested-With':'XMLHttpRequest',
    'Referer':'https://unsplash.com/',
    'Host':'unsplash.com',
    'Connection':'keep-alive'
}

然后,我们得获取json数据,这里我用requests库,然后从中解析出id,将其组装成图片的下载路径,然后向此路径发送请求,获取重定向后的真实下载路径,再次对真实下载路径发送请求。

#解析一个页面的json
def json_parse(page):
    params = {
        'page': str(page),
        'per_page': '12',
        'order_by': 'latest'
    }
    url = base_url + urlencode(params)
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        json = response.json()
        photo_url_download_true=[]
        photo_id=[]
        data=[]
        for i in range(len(json)):
            photo_url_id = json[i].get('id')
            #print(photo_url_id)
            photo_url_download = 'https://unsplash.com/photos/' + photo_url_id + '/download?force=true'
            #获取重定向后的url
            response1 = requests.get(photo_url_download, headers=headers, allow_redirects=False)
            photo_url_download = response1.headers['Location']
            photo_url_download_true.append(photo_url_download)
            photo_id.append(photo_url_id)
        data.append(photo_url_download_true)
        data.append(photo_id)
        return data
    else:print('获取重定向后的url失败')

接下来,我们将获取到的图片数据写入文件,这里,我们构造一个写入文件的函数。

#将照片写入文件
def write_to_file(photo_url_download_true,id,page,number):
    response2 = requests.get(photo_url_download_true)
    if response2.status_code == 200:
        file_path = "e:/Unsplash/" + id + ".jpg"
        with open(file_path, 'wb') as f:
            f.write(response2.content)
        print('正在下载第%d张照片.....' % (page*11+number+1))
        print(id + ".jpg" + '下载成功')
    else:
        print('下载失败')

 现在,我们的大部分代码就完成了,我们将剩余代码完成。当然,为了更加完善和完整,我还给代码加了一个计算函数。

#计算函数
def calc():
    page=(NUMBER_OF_PHOTO -1)// 12
    number=NUMBER_OF_PHOTO -page*12
    return [page,number]

#主函数
def main():
    pages=calc()[0]
    numbers=calc()[1]
    for page in range(pages):
        print('********************请耐心等待********************')
        data = json_parse(page)
        for count in range(12):
            write_to_file(data[0][count],data[1][count],page,count)
    print("********************请耐心等待********************")
    data=json_parse(pages)
    for number in range(numbers):
        write_to_file(data[0][number],data[1][number],pages,number)

if __name__=='__main__':
    main()

终于,大功告成。

最后,效果图摆上。

源码: https://github.com/kingdowliu/Unsplash_Spider/blob/master/unsplash.py

[1]Ajax: Ajax 是一种用于创建快速动态网页的技术,是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术,通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

[2]json: json是一种轻量级的数据交换格式,通过数组与对象的组合来表示数据。在 JS 语言中,一切都是对象。因此,任何支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。但是对象和数组是比较特殊且常用的两种类型。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值