Python3爬虫图片抓取

(1)实战背景

1 

上图的网站的名字叫做Unsplash,免费高清壁纸分享网是一个坚持每天分享高清的摄影图片的站点,每天更新一张高质量的图片素材,全是生活中的景象作品,清新的生活气息图片可以作为桌面壁纸也可以应用于各种需要的环境。

看到这么优美的图片,是不是很想下载啊。每张图片我都很喜欢,批量下载吧,不多爬,就下载50张好了。

2)实战进阶

我们已经知道了每个html标签都有各自的功能。<a>标签存放一下超链接,图片存放在哪个标签里呢?html规定,图片统统给我放到<img>标签中!既然这样,我们截取就Unsplash网站中的一个<img>标签,分析一下:

<img alt="Snow-capped mountain slopes under blue sky" src="https://images.unsplash.com/photo-1428509774491-cfac96e12253?dpr=1&

可以看到,<img>标签有很多属性,有alt、src、class、style属性,其中src属性存放的就是我们需要的图片保存地址,我们根据这个地址就可以进行图片的下载。

那么,让我们先捋一捋这个过程:

  • 使用requeusts获取整个网页的HTML信息;
  • 使用Beautiful Soup解析HTML信息,找到所有<img>标签,提取src属性,获取图片存放地址;
  • 根据图片存放地址,下载图片。

我们信心满满地按照这个思路爬取Unsplash试一试,编写代码如下:

# -*- coding:UTF-8 -*-
import requests
if __name__ == '__main__':target = 'https://unsplash.com/'req = requests.get(url=target)print(req.text)

按照我们的设想,我们应该能找到很多<img>标签。但是我们发现,除了一些<script>标签和一些看不懂的代码之外,我们一无所获,一个<img>标签都没有!跟我们在网站审查元素的结果完全不一样,这是为什么? 

答案就是,这个网站的所有图片都是动态加载的!网站有静态网站和动态网站之分,上一个实战爬取的网站是静态网站,而这个网站是动态网站,动态加载有一部分的目的就是为了反爬虫。

对于什么是动态加载,你可以这样理解:我们知道化妆术学的好,贼厉害,可以改变一个人的容貌。相应的,动态加载用的好,也贼厉害,可以改变一个网站的容貌。

动态网站使用动态加载常用的手段就是通过调用JavaScript来实现的。怎么实现JavaScript动态加载,我们不必深究,我们只要知道,动态加载的JavaScript脚本,就像化妆术需要用的化妆品,五花八门。有粉底、口红、睫毛膏等等,它们都有各自的用途。动态加载的JavaScript脚本也一样,一个动态加载的网站可能使用很多JavaScript脚本,我们只要找到负责动态加载图片的JavaScript脚本,不就找到我们需要的链接了吗?

对于初学者,我们不必看懂JavaScript执行的内容是什么,做了哪些事情,因为我们有强大的抓包工具,它自然会帮我们分析。这个强大的抓包工具就是Fiddler:http://www.telerik.com/fiddler

PS:也可以使用浏览器自带的Networks,但是我更推荐这个软件,因为它操作起来更高效。

安装方法很简单,傻瓜式安装,一直下一步即可,对于经常使用电脑的人来说,应该没有任何难度。

这个软件的使用方法也很简单,打开软件,然后用浏览器打开我们的目标网站,以Unsplash为例,抓包结果如下:

3

我们可以看到,上图左侧红框处是我们的GET请求的地址,就是网站的URL,右下角是服务器返回的信息,我们可以看到,这些信息也是我们上一个程序获得的信息。这个不是我们需要的链接,我们继续往下看。

4

我们发现上图所示的就是一个JavaScript请求,看右下侧服务器返回的信息是一个json格式的数据。这里面,就有我们需要的内容。我们局部放大看一下:

5

这是Fiddler右侧的信息,上面是请求的Headers信息,包括这个Javascript的请求地址:http://unsplash.com/napi/feeds/home,其他信息我们先不管,我们看看下面的内容。里面有很多图片的信息,包括图片的id,图片的大小,图片的链接,还有下一页的地址。这个脚本以json格式存储传输的数据,json格式是一种轻量级的数据交换格式,起到封装数据的作用,易于人阅读和编写,同时也易于机器解析和生成。这么多链接,可以看到图片的链接有很多,根据哪个链接下载图片呢?先别急,让我们继续分析:

QQ截图20180517155307

在这个网站,我们可以按这个按钮进行图片下载。我们抓包分下下这个动作,看看发送了哪些请求。

https://unsplash.com/photos/1PrQ2mHW-Fo/download?force=true
https://unsplash.com/photos/JX7nDtafBcU/download?force=true
https://unsplash.com/photos/HCVbP3zqX4k/download?force=true

通过Fiddler抓包,我们发现,点击不同图片的下载按钮,GET请求的地址都是不同的。但是它们很有规律,就是中间有一段代码是不一样的,其他地方都一样。中间那段代码是不是很熟悉?没错,它就是我们之前抓包分析得到json数据中的照片的id。我们只要解析出每个照片的id,就可以获得图片下载的请求地址,然后根据这个请求地址,我们就可以下载图片了。那么,现在的首要任务就是解析json数据了。

json格式的数据也是分层的。可以看到next_page里存放的是下一页的请求地址,很显然Unsplash下一页的内容,也是动态加载的。在photos下面的id里,存放着图片的id,这个就是我们需要获得的图片id号。

怎么编程提取这些json数据呢?我们也是分步完成:

  • 获取整个json数据
  • 解析json数据

编写代码,尝试获取json数据:

# -*- coding:UTF-8 -*-
import requests
if __name__ == '__main__':target = 'http://unsplash.com/napi/feeds/home'req = requests.get(url=target) print(req.text)

很遗憾,程序报错了,问题出在哪里?通过错误信息,我们可以看到SSL认证错误,SSL认证是指客户端到服务器端的认证。一个非常简单的解决这个认证错误的方法就是设置requests.get()方法的verify参数。这个参数默认设置为True,也就是执行认证。我们将其设置为False,绕过认证不就可以了?

6

有想法就要尝试,编写代码如下:

# -*- coding:UTF-8 -*-
import requests
if __name__ == '__main__':target = 'http://unsplash.com/napi/feeds/home'req = requests.get(url=target, verify=False)print(req.text)

认证问题解决了,又有新问题了:

7

可以看到,我们GET请求又失败了,这是为什么?这个网站反爬虫的手段除了动态加载,还有一个反爬虫手段,那就是验证Request Headers。接下来,让我们分析下这个Requests Headers:

8

我截取了Fiddler的抓包信息,可以看到Requests Headers里又很多参数,有Accept、Accept-Encoding、Accept-Language、DPR、User-Agent、Viewport-Width、accept-version、Referer、x-unsplash-client、authorization、Connection、Host。它们都是什么意思呢?

专业的解释能说的太多,我挑重点:

  • User-Agent:这里面存放浏览器的信息。可以看到上图的参数值,它表示我是通过Windows的Chrome浏览器,访问的这个服务器。如果我们不设置这个参数,用Python程序直接发送GET请求,服务器接受到的User-Agent信息就会是一个包含python字样的User-Agent。如果后台设计者验证这个User-Agent参数是否合法,不让带Python字样的User-Agent访问,这样就起到了反爬虫的作用。这是一个最简单的,最常用的反爬虫手段。
  • Referer:这个参数也可以用于反爬虫,它表示这个请求是从哪发出的。可以看到我们通过浏览器访问网站,这个请求是从https://unsplash.com/,这个地址发出的。如果后台设计者,验证这个参数,对于不是从这个地址跳转过来的请求一律禁止访问,这样就也起到了反爬虫的作用。
  • authorization:这个参数是基于AAA模型中的身份验证信息允许访问一种资源的行为。在我们用浏览器访问的时候,服务器会为访问者分配这个用户ID。如果后台设计者,验证这个参数,对于没有用户ID的请求一律禁止访问,这样就又起到了反爬虫的作用。

Unsplash是根据哪个参数反爬虫的呢?根据我的测试,是authorization。我们只要通过程序手动添加这个参数,然后再发送GET请求,就可以顺利访问了。怎么什么设置呢?还是requests.get()方法,我们只需要添加headers参数即可。编写代码如下:

# -*- coding:UTF-8 -*-
import requests
if __name__ == '__main__':target = 'http://unsplash.com/napi/feeds/home'headers = {'authorization':'your Client-ID'}req = requests.get(url=target, headers=headers, verify=False)print(req.text)

headers参数值是通过字典传入的。记得将上述代码中your Client-ID换成诸位自己抓包获得的信息。代码运行结果如下:

9

皇天不负有心人,可以看到我们已经顺利获得json数据了,里面有next_page和照片的id。接下来就是解析json数据。根据我们之前分析可知,next_page放在了json数据的最外侧,照片的id放在了photos->id里。我们使用json.load()方法解析数据,编写代码如下:

# -*- coding:UTF-8 -*-
import requests, json
if __name__ == '__main__':target = 'http://unsplash.com/napi/feeds/home'headers = {'authorization':'your Client-ID'}req = requests.get(url=target, headers=headers, verify=False)html = json.loads(req.text)next_page = html['next_page']print('下一页地址:',next_page)for each in html['photos']:print('图片ID:',each['id'])

解析json数据很简单,跟字典操作一样,就是字典套字典。json.load()里面的参数是原始的json格式的数据。程序运行结果如下:

10

图片的ID已经获得了,再通过字符串处理一下,就生成了我们需要的图片下载请求地址。根据这个地址,我们就可以下载图片了。下载方式,使用直接写入文件的方法。

(3)整合代码

每次获取链接加一个1s延时,因为人在浏览页面的时候,翻页的动作不可能太快。我们要让我们的爬虫尽量友好一些。

# -*- coding:UTF-8 -*-
import requests, json, time, sys
from contextlib import closingclass get_photos(object):def __init__(self):self.photos_id = []self.download_server = 'https://unsplash.com/photos/xxx/download?force=trues'self.target = 'http://unsplash.com/napi/feeds/home'self.headers = {'authorization':'Client-ID c94869b36aa272dd62dfaeefed769d4115fb3189a9d1ec88ed457207747be626'}"""函数说明:获取图片IDParameters:无Returns:无Modify:2017-09-13"""   def get_ids(self):req = requests.get(url=self.target, headers=self.headers, verify=False)html = json.loads(req.text)next_page = html['next_page']for each in html['photos']:self.photos_id.append(each['id'])time.sleep(1)for i in range(5):req = requests.get(url=next_page, headers=self.headers, verify=False)html = json.loads(req.text)next_page = html['next_page']for each in html['photos']:self.photos_id.append(each['id'])time.sleep(1)"""函数说明:图片下载Parameters:无Returns:无Modify:2017-09-13"""   def download(self, photo_id, filename):headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36'}target = self.download_server.replace('xxx', photo_id)with closing(requests.get(url=target, stream=True, verify = False, headers = self.headers)) as r:with open('%d.jpg' % filename, 'ab+') as f:for chunk in r.iter_content(chunk_size = 1024):if chunk:f.write(chunk)f.flush()if __name__ == '__main__':gp = get_photos()print('获取图片连接中:')gp.get_ids()print('图片下载中:')for i in range(len(gp.photos_id)):print('  正在下载第%d张图片' % (i+1))gp.download(gp.photos_id[i], (i+1))

下载速度还行,有的图片下载慢是因为图片太大。可以看到右侧也打印了一些警报信息,这是因为我们没有进行SSL验证。

20170930130019403


原文作者:Jack-Cui

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/28564.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爬虫实战 爬取谷歌图片 Google images

目标 #date&#xff1a;2020.5.25 #author:pmy #aim:爬取google图片 本次爬取主要是为了练习selenium。 分析 爬取的目标如下图&#xff0c;爬取猫猫图片 将google图片顺利爬下来。 由于google图片界面是属于那种往下划会在本页面中加载出更多信息&#xff0c;但未刷新的机…

Python爬虫爬取Google图片

文章目录 urlliburllib.request.urlretrieve urllib3 in python3PoolManagerRequest BeautifulSoup安装 Installation一些函数 Some functionsget_textfind_all(name, attrs, recursive, string, limit, **kwargs)name - 通过标签名搜索kwargs - keyword arguments 关键字参数进…

Python——爬虫抓取图片

/* * Copyright (c) 2014, 烟台大学计算机学院 * All rights reserved. * 文件名称&#xff1a;test.cpp * 作 者&#xff1a;李晓凯 * 完成日期&#xff1a;2019年 8 月 19 日 * 版 本 号&#xff1a;v1.0 * * 问题描述&#xff1a; * 输入描述&#xff1a; * 程…

python爬虫(爬取图片)

在家无聊写的爬虫程序&#xff0c;用来爬取图片&#xff0c;由于这个是好久之前写的&#xff0c;有点忘了&#xff0c;写的不详细&#xff0c;后面再写一份详细的 爬虫的基本原理就是&#xff1a; 发起请求->获取响应->解析内容->保存数据 第一步&#xff1a;发…

面试常见题(荷兰国旗问题

面试常见题&#xff0c;荷兰三色国旗问题 挺有意思的 #include<bits/stdc.h> using namespace std; int main(){vector<int>str{2, 3, 1, 9, 7, 6, 1, 4, 5,4};int nstr.size();int target4;int l-1,rn;int p0;//这里不能是l<r哦&#xff0c;p代表数组遍历指针…

快速排序之荷兰国旗问题

描述 荷兰国旗有三横条块构成&#xff0c;自上到下的三条块颜色依次为红、白、蓝。现有若干由红、白、蓝三种颜色的条块序列&#xff0c;要将它们重新排列使所有相同颜色的条块在一起。本问题要求将所有红色的条块放最左边、所有白色的条块放中间、所有蓝色的条块放最右边。 …

从糖尿病捆绑支付看荷兰整合医疗

来源:中国数字科技馆 所谓捆绑支付模式,是指对于患有特定疾病的患者,在涉及多个照护提供方的时候,通过单一途径即可支付所接受的所有服务。在荷兰,随着老年人口及慢性疾病患者的增加,整合医疗开始受到政策决策者和保健提供者的关注,并将整合医疗定位为有前瞻性的、多学…

荷兰旗问题(三色旗排序)

摘要&#xff1a; 荷兰旗问题是三色排序&#xff0c;即某一组数据&#xff0c;元素的值只能为a,b ,c。把这组数据按照a, b, c的顺序排序。 本文介绍了一种时间复杂度为O&#xff08;n&#xff09;&#xff0c;空间复杂度O&#xff08;1&#xff09;的算法。 1. 问题描述 某…

荷兰国旗问题(分三块)

在说 “荷兰国旗” 问题之前&#xff0c;首先来看一个引例。 给定一个数组arr&#xff0c;和一个数num&#xff0c;请把小于等于num的数放在数组的左边&#xff0c;大于num的数放在数组的右边。要求额外空间复杂度O(1&#xff09;,时间复杂度 O(N&#xff09; 分析&#xff1…

荷兰国旗问题

Cousera Algorithms PartI第二周课后问答题&#xff0c;有这样一道题&#xff0c;当时没什么想法&#xff0c;直到学了第三周的归并排序&#xff0c;才弄明白要怎么做&#xff0c;这里记录一下自己的想法与最终代码。 问题描述 简而言之&#xff0c;这道题就是有红白蓝三种颜…

算法:荷兰国旗问题

什么是荷兰国旗问题 荷兰国旗是由红白蓝3种颜色的条纹拼接而成&#xff0c;如下图所示&#xff1a; 假设这样的条纹有多条&#xff0c;且各种颜色的数量不一&#xff0c;并且随机组成了一个新的图形&#xff0c;新的图形可能如下图所示&#xff0c;但是绝非只有这一种情况&am…

快排-荷兰国旗

在使用partition-exchange排序算法时&#xff0c;如快速排序算法&#xff0c;我们会遇到一些问题&#xff0c;比如重复元素太多&#xff0c;降低了效率&#xff0c;在每次递归中&#xff0c;左边部分是空的(没有元素比关键元素小)&#xff0c;而右边部分只能一个一个递减移动。…

BUUCTF 荷兰宽带数据泄露

题目 RouterPassView RouterPassView官方下载-RouterPassView中文免费版-华军软件园 ​ RouterPassView,大多数现代路由器允许您备份到一个文件路由器的配置&#xff0c;然后从文件中恢复配置时的需要。路由器的备份文件通常包含了像您的ISP的用户名重要数据/密码&#xff0c…

荷兰国旗问题以及快速排序

文章目录 一、荷兰国旗问题1、啥是荷兰国旗问题2、荷兰国旗问题的抽象3、解决的思路4、详细的参考代码 二、快速排序1、啥是快排&#xff08;排序流程&#xff09;2、抽象后的快排流程3、详细的参考代码 大家好&#xff0c;我是周一。 最近几篇算法&#xff0c;我们都是聊的归…

拍卖理论 英式拍卖 和 荷兰式拍卖 是什么

拍卖理论 源自Vickrey&#xff08;1961&#xff09;的早期研究&#xff0c;其因此获得1996年的诺贝尔经济学奖。 目标一般为&#xff1a;拍卖人的收益最大化、社会的整体效率最优化 对科研和商业方面有非常价值 英式拍卖 又称增价拍卖。拍品的起拍价格即最低期望价格&#…

谈腾讯地图web api如何实现类似百度地图内置的城市切换、关键字输入提示功能

PC WEB端新增客户的时候需要填写客户地址和联系人信息&#xff0c;包括&#xff1a;省市区、街道、详细地址和经纬度以及联系人、固话和移动电话。获取客户地址信息之前用的是百度地图&#xff0c;由于小程序中客户拜访时&#xff0c;需要对客户进行定位、距离计算&#xff0c;…

数学系列 (二)自然数、分数、小数、算数、代数

从无到有 数的概念 出生不久的孩子你觉的他认识1、2、3类似的数字吗&#xff1f;应该都不知道&#xff0c;可见数字的概念也是随着我们人类成长逐渐认识到的&#xff0c;英国经济学创立者亚当斯密说“数是人类在精神上制造出来的最抽象的概念”&#xff0c;属于逻辑思维里面的…

html 省份,城市 选择器附效果图

开发交流QQ群: 173683895 173683895 526474645 人满的请加其它群 效果图&#xff1a; 源码&#xff1a; <!DOCTYPE html> <html><head><meta charset"UTF-8"><link href"https://cdn.bootcss.com/bootstrap/3.3.7/css/boots…

深圳前海和后海的地理位置划分

前海后海的地理位置 前海和后海主要是相对于珠江口而言的&#xff0c;面向珠江口的为前海&#xff0c;背向珠江口的为后海或面向深圳湾的为后海。 前海知识拓展 https://www.sohu.com/a/490380431_124752

Python实现天气查询功能(外加Excel技巧)

昨天在网上发现了一个非常方便的天气API&#xff0c;就用Python试着用了一下。参数是挺少的&#xff0c;用起来也方便&#xff0c;但是那个城市代码确实是搞了我好长时间。 一、介绍 我们先来看一下实现的程序有什么功能&#xff1a; 功能也是非常简单的&#xff0c;输入城市…