python批量下载网站马拉松照片的完整步骤


Posted in Python onDecember 05, 2018

前言

目前学习python几个月了,由于自己比较喜欢跑马拉松,已经跑过了很多场比赛,前些天就写了个简单的爬虫爬取了网上三千多场马拉松比赛的报名信息。

今年5月27日,我又参加了巴图鲁关门山壹佰越野50公里组的比赛,这里的“巴图鲁”源自蒙古语“英雄”的意思,这场比赛也是出了名的虐,地点在辽宁省本溪市 · 关门山国家森林公园,累计爬升3655m。当天早上六点准时出发,刚跑没多久就来了很长一段陡峭的台阶……此处省略一万字……最终经过很多小时的艰苦奋战完成了比赛。

赛后去官网想找几张好看的图片发朋友圈,打开官网赛事图片链接到了爱运动的一个网页http://runnerbar.com/yd_runnerbar/album/pc?type=3&activity_id=10712,这是个单页面的网页,不断滚动会自动加载更多的图片,我把页面一点点滚动找了很长一段时间根本找不到我的照片,刷新一下页面照片又从头开始了,实在不能忍。于是,我想要不把图片全部下载到本地查看吧,想干就干。

1. 分析

1.1 Chrome调试

在chrome浏览器里输入快捷键Cmd + Opt + I(Windows上是F12,或Ctrl + Shift + I),将调试选项切到Network,如下

python批量下载网站马拉松照片的完整步骤

一个个观察此网页发送的请求,找到和图片相关的请求

python批量下载网站马拉松照片的完整步骤

这是一个get请求,初步分析里面的参数,activity_id代表赛事id,page和pageSize分别代表页数和每页大小,接着将请求放在postman上印证

python批量下载网站马拉松照片的完整步骤

1.2请求分析

在postman里加了三个参数成功返回了一个json格式的值,第一阶段很顺利,接着分析里面的返回值,下面取了其中的一个元素

{
"album": {
 "activity_photo_count": 6984,
 "searchResultList": [
 {
  "id": "32926651",
  "uid": 50392,
  "name": "巴图鲁关东越野",
  "user_name": null,
  "user_img": "http://oss.runnerbar.com/img/user_upload/origin/20180526/1527305285356_fb59065d_18ce_478b_a3aa_259783f4cd5b.jpg",
  "create_time": 1527313780000,
  "image_height": 3648,
  "image_width": 5472,
  "orientation": 1,
  "url_hq": "http://oss.runnerbar.com/img/watermark/user_upload/origin/20180526/1527313783392_235c5cea_5d0c_4cd7_afc6_0ba37cdc7c1d.jpg?quality=h",
  "url_lq": "http://oss.runnerbar.com/img/watermark/user_upload/origin/20180526/1527313783867_7d986351_fde4_418a_8fb3_1723dcb38aec.jpg",
  "content": null,
  "is_like": 0,
  "like_count": null,
  "comment_count": 0
 }}

这是个json格式,最外层里有个album元素,album里包含了图片总数量activity_photo_count和图片信息的数组searchResultList。每张图片包含了id、uid、user_img、create_time等等,和图片路径相关的有三个值分别是user_img、url_hq、url_lq,其中的user_img打开后发现是赛事的宣传logo,剩下的url_hq、url_lq根据命名就很容易猜想到这是对应的两种尺寸的图片,用浏览器分别打开,果不其然正是想要的图片路径。

2.代码

2.1

上面已经知道了请求url和参数,下面就是需要将这些用代码实现出来。首先是发请求

url='http://m.yundong.runnerbar.com/yd_mobile/share/album.json'
para = {'activity_id':id,'page':page,'pageSize':100}
header = {}
r = requests.post(url,data=para,headers= header)

请求的返回值是json,json内容在上面已经贴出来了这里就不再重复,接着解析这个json

json_r = r.json()
parsed_json = json_r['album']['searchResultList']
activity = {}
items = []
count = json_r['album']['activity_photo_count']

这里就取到了图片总数量和图片信息的数组,这个请求参数是page和pageSize,一个请求只能取到一部分图片信息并不能把所有的图片都取出来。那能不能把所有图片分成一页返回呢?于是在postman上做了实验,将page=1,pageSize=10000发送,结果并不是想要的,真正返回的图片数量是100。说明这个接口做了校验,每个分页最大数量是100。看来投机取巧是不行了,分页还是要做的。

首先将单个请求封装成方法,传入page返回对应page的图片信息数组

def getRaceInfo(id,page):
 url='http://m.yundong.runnerbar.com/yd_mobile/share/album.json'
 para = {'activity_id':id,'page':page,'pageSize':100}
 header = {}
 r = requests.post(url,data=para,headers= header)
 json_r = r.json()
 parsed_json = json_r['album']['searchResultList']
 activity = {}
 items = []
 count = json_r['album']['activity_photo_count']
 for item in parsed_json:
 # print(item['user_img'])
 items.append(item)
 activity['items'] = items
 activity['count'] = count
return activity

图片的做数量是count,每页分100张图片,起点是第1页,那么总的分页数量就是count/100+2,分页的代码就应该是这样的

for i in range(1,int(count/100+2)):
 data = getRaceInfo(id,i)['items']

这里只是贴了一小段代码,完整代码可以参见上面的github地址

2.2 下载

有了图片在url,下载图片就更简单了,直接上代码

def save_img(img_url,file_name,file_path='book'):
#保存图片到磁盘文件夹 file_path中,默认为当前脚本运行目录下的 book\img文件夹
try:
 if not os.path.exists(file_path):
 print('文件夹',file_path,'不存在,重新建立')
 #os.mkdir(file_path)
 os.makedirs(file_path)
 #获得图片后缀
 file_suffix = os.path.splitext(img_url)[1]
 #拼接图片名(包含路径)
 filename = '{}{}{}{}'.format(file_path,os.sep,file_name,file_suffix)
 #下载图片,并保存到文件夹中
 urllib.request.urlretrieve(img_url,filename=filename)
except IOError as e:
 print('文件操作失败',e)
except HTTPError as e:
 print('Error code: ', e.code)
except Exception as e:
 print('错误 :',e)

运行python,查看本地文件

几千张图片很快下载到了本地

python批量下载网站马拉松照片的完整步骤

这时又有了新的想法,既然可以下载关门山越野的图片,是不是可以把爱运动里所有的图片都下载下来,说干就干。于是我将赛事id定义成参数,写个方法遍历id。改动了几行从新运行,几个小时后程序还在运行但是图片占用的大小已经超过了7G,

python批量下载网站马拉松照片的完整步骤

打开文件里面包含了各个赛事的图片,眼看图片越来越多加上我的mac存储空间有限最终停止了下载,但是这个思路应该是可行的。

源码地址: https://github.com/halibobo/runnerbar-image (本地下载)

最后

整个过程从开始到结束都在一天内完成的,代码里也没有什么复杂的逻辑,但完成之后心里还是有很多的满足感。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python进阶教程之循环对象
Aug 30 Python
Python中集合的内建函数和内建方法学习教程
Aug 19 Python
Python新手们容易犯的几个错误总结
Apr 01 Python
利用Python+Java调用Shell脚本时的死锁陷阱详解
Jan 24 Python
Python subprocess模块详细解读
Jan 29 Python
对python中Librosa的mfcc步骤详解
Jan 09 Python
Flask框架学习笔记之路由和反向路由详解【图文与实例】
Aug 12 Python
结合OpenCV与TensorFlow进行人脸识别的实现
Oct 10 Python
Python使用Pygame绘制时钟
Nov 29 Python
python实现登录与注册系统
Nov 30 Python
如何用python识别滑块验证码中的缺口
Apr 01 Python
Python字典和列表性能之间的比较
Jun 07 Python
解决python3中cv2读取中文路径的问题
Dec 05 #Python
利用Python求阴影部分的面积实例代码
Dec 05 #Python
python之cv2与图像的载入、显示和保存实例
Dec 05 #Python
python存储16bit和32bit图像的实例
Dec 05 #Python
Python随机生成身份证号码及校验功能
Dec 04 #Python
python 从文件夹抽取图片另存的方法
Dec 04 #Python
使用Python实现微信提醒备忘录功能
Dec 04 #Python
You might like
php设计模式 State (状态模式)
2011/06/26 PHP
PHP防止注入攻击实例分析
2014/11/03 PHP
实现PHP框架系列文章(6)mysql数据库方法
2016/03/04 PHP
php发送http请求的常用方法分析
2016/11/08 PHP
老生常谈php中传统验证与thinkphp框架(必看篇)
2017/06/10 PHP
常用Extjs工具:Extjs.util.Format使用方法
2012/03/22 Javascript
jquery中html、val与text三者属性取值的联系与区别介绍
2013/12/29 Javascript
在页面上用action传递参数到后台出现乱码的解决方法
2013/12/31 Javascript
JSON字符串和对象之间的转换详解
2015/05/26 Javascript
JavaScript中的splice()方法使用详解
2015/06/09 Javascript
浅谈JavaScript函数的四种存在形态
2016/06/08 Javascript
nodejs的压缩文件模块archiver用法示例
2017/01/18 NodeJs
原生JS实现《别踩白块》游戏(兼容IE)
2017/02/20 Javascript
在Vue中使用this.$store或者是$route一直报错的解决
2019/11/08 Javascript
JS实现滑动拼图验证功能完整示例
2020/03/29 Javascript
vue 使用原生组件上传图片的实例
2020/09/08 Javascript
Python实现桶排序与快速排序算法结合应用示例
2017/11/22 Python
对Python 语音识别框架详解
2018/12/24 Python
解决python给列表里添加字典时被最后一个覆盖的问题
2019/01/21 Python
python多线程抽象编程模型详解
2019/03/20 Python
Python 循环终止语句的三种方法小结
2019/06/24 Python
Python解析json代码实例解析
2019/11/25 Python
Pytorch 扩展Tensor维度、压缩Tensor维度的方法
2020/09/09 Python
CSS3等相关属性制作分页导航实现代码
2012/12/24 HTML / CSS
css3制作彩色边线3d立体按钮的示例(css3按钮)
2014/05/06 HTML / CSS
NUK奶瓶美国官网:NUK美国
2016/09/26 全球购物
大学生通用个人的自我评价
2014/02/10 职场文书
医院深入开展党的群众路线教育实践活动实施方案
2014/08/27 职场文书
落实八项规定专题民主生活会对照检查材料
2014/09/15 职场文书
2014教师党员个人自我评议
2014/09/20 职场文书
小学五年级(说明文3篇)
2019/08/13 职场文书
2020优秀员工演讲稿(三篇)
2019/10/17 职场文书
字典算法实现及操作 --python(实用)
2021/03/31 Python
ubuntu安装jupyter并设置远程访问的实现
2022/03/31 Python
pt-archiver 主键自增
2022/04/26 MySQL
MySQL串行化隔离级别(间隙锁实现)
2022/06/16 MySQL