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读取Excel的方法实例分析
Jul 11 Python
python3实现ftp服务功能(客户端)
Mar 24 Python
python 上下文管理器使用方法小结
Oct 10 Python
Python使用matplotlib实现绘制自定义图形功能示例
Jan 18 Python
Python中的defaultdict与__missing__()使用介绍
Feb 03 Python
python方法生成txt标签文件的实例代码
May 10 Python
Python爬虫之正则表达式的使用教程详解
Oct 25 Python
pandas 数据结构之Series的使用方法
Jun 21 Python
python可视化实现KNN算法
Oct 16 Python
logging level级别介绍
Feb 21 Python
python实现udp聊天窗口
Mar 31 Python
python matplotlib:plt.scatter() 大小和颜色参数详解
Apr 14 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
re0第二季蕾姆被制作组打入冷宫!艾米莉亚女主扶正,原因唏嘘
2020/04/02 日漫
JS 网站性能优化笔记
2011/05/24 PHP
详解PHP变量传值赋值和引用赋值变量销毁
2019/03/23 PHP
JavaScript 存在陷阱 删除某一区域所有节点
2010/05/10 Javascript
最短的javascript:地址栏载入脚本代码
2011/10/13 Javascript
checkbox设置复选框的只读效果不让用户勾选
2013/08/12 Javascript
javascript去掉前后空格的实例
2013/11/07 Javascript
JavaScript中instanceof运算符的用法总结
2013/11/19 Javascript
js实现键盘上下左右键选择文字并显示在文本框的方法
2015/05/07 Javascript
Bootstrap每天必学之导航
2015/11/26 Javascript
拥有一个属于自己的javascript表单验证插件
2016/03/24 Javascript
jquery判断iPhone、Android设备类型
2016/09/14 Javascript
javascript 中Cookie读、写与删除操作
2017/03/29 Javascript
详解Angular之constructor和ngOnInit差异及适用场景
2017/06/22 Javascript
jquery 获取索引值在一定范围的列表方法
2018/01/25 jQuery
vue实现裁切图片同时实现放大、缩小、旋转功能
2018/03/02 Javascript
JS实现倒计时图文效果
2018/11/17 Javascript
在vue中实现某一些路由页面隐藏导航栏的功能操作
2020/09/21 Javascript
解决elementui表格操作列自适应列宽
2020/12/28 Javascript
使用Python编写一个在Linux下实现截图分享的脚本的教程
2015/04/24 Python
python中实现k-means聚类算法详解
2017/11/11 Python
Django-rest-framework中过滤器的定制实例
2020/04/01 Python
使用keras框架cnn+ctc_loss识别不定长字符图片操作
2020/06/29 Python
临床医学大学生求职信
2013/09/28 职场文书
员工自我鉴定
2013/10/09 职场文书
业务员岗位职责
2013/11/16 职场文书
自我评价怎么写正确呢?
2013/12/02 职场文书
青年文明号服务承诺
2014/03/31 职场文书
社会治安综合治理管理责任书
2014/04/16 职场文书
班级读书活动总结
2014/06/30 职场文书
2015年企业团支部工作总结
2015/05/21 职场文书
活动主持人开场白
2015/05/28 职场文书
辞职离别感言
2015/08/04 职场文书
高中班长竞选稿
2015/11/20 职场文书
JavaScript选择器函数querySelector和querySelectorAll
2021/11/27 Javascript
MybatisPlus EntityWrapper如何自定义SQL
2022/03/22 Java/Android