「微硬核」下图下到手抽筋?手把手教你用脚本解救你的手
toqiye 2024-11-27 21:09 4 浏览 0 评论
我们时常会在网上浏览网页的时候,看到很多美美的图片。有些时候因为喜欢想保存下来,有些时候因为网页浏览太慢,就想把图片下载到电脑上方便查看。但是,下载图片除非是网站提供了打包下载的功能。否则都是一张张点右键另存为,然后选择保存路径,才能下载下来。
好一点的情况是,一套图片几十张都在一个页面,虽然操作到手抽筋,但好歹一个页面搞定。但,有些每页一个的,就需要打开几十个页面再一个个保存。更何况,面对美美的图片,我们想的是,我!全!要!忙到手抽筋也没法把一个网站的图片全部保存下来啊。
好的,你需要的是一个自动下载图片的工具。网上其实有一些类似工具,但是其实自己写也是非常容易的。本文就是手把手教你写一个下载工具,自由下载,解放双手。
写工具用啥语言?“人生苦短,我用python”,所以当然是python了。
需要预先准备的:
- https://www.python.org/downloads/release/python-375/ 下载python,一般都是windows版本的,现在基本都64位的,所以选择Windows x86-64 executable installer。安装的时候记得选择“add to path”的选项。
- 安装完python,咱们还得装几个方便使用的库,bs4和requests。bs4就是beautifulsoup,解析html的,requests就是方便http请求的。打开powershell,执行下面的命令
pip install bs4 -i https://mirrors.aliyun.com/pypi/simple/ pip install requests -i https://mirrors.aliyun.com/pypi/simple/
为加快安装速度,咱们选用的是pip的国内镜像。 -i https://mirrors.aliyun.com/pypi/simple/就是指定阿里云的pip镜像。
接下来选择一个下载图片的网站,为避免广告导流嫌疑(虽然没啥量),我百度上随便搜了一个,中关村的图片精选页面 http://bbs.zol.com.cn/dcbbs/topic。当然实际大家自己用的肯定是自己要下载图片的页面地址。
好的,下面要开始码了,码之前我们先说说思路。总的来说,就是抓取站点页面,然后把页面html解析之后获取图片地址,再下载图片,保存到本地。难点就是,为了抓取全部页面,我们要解析html的时候,获取当前页面所有的本站地址,依次去请求处理,还得注意排除已经请求过的。
coding begin...
咱们打开自带的edle编辑器,File->New File创建一个新文件,保存为downloader.py。
先加载库
import bs4 import requests import os import logging import urllib.parse import sys
整个功能咱们划分成几个模块,功能分别如下:
- 请求并解析页面,获取当前页面图片地址和站内链接地址
- 根据上一步返回的站内链接地址,判断是否重复,如果没处理过,则使用上一步的方式处理该链接
- 请求图片地址,读取之后保存到本地
咱们要完成的第一个功能模块就是请求并解析页面的方法,因为功能简单单一,都用函数开发,不采用类。
headers = {'user-agent': 'image downloader/0.0.1'} def is_same_domain(base_url,url): base_url_parsed = urllib.parse.urlparse(base_url) url_parsed = urllib.parse.urlparse(url) return base_url_parsed.netloc == url_parsed.netloc def process_page(url): ''' 获取url下所有图片以及站内链接 ''' images = [] site_urls=[] try: page_req = requests.get(url, headers=headers) if page_req.status_code != 200: logging.error(url+' http code: '+str(page_req.status_code)) return images,site_urls page_parsed = bs4.BeautifulSoup(page_req.text, 'html.parser') images = [ img.attrs['src'] for img in page_parsed.find_all('img')] site_urls= [ a.attrs['href'] for a in page_parsed.find_all('a') if 'href' in a.attrs and is_same_domain(url,a.attrs['href'])] logging.info("processed "+url) return images,site_urls except Exception as e: logging.error(url+' '+str(e)) return images,site_urls
工具函数is_same_domain判断解析的网页地址是否和当前处理的地址是一个域名。process_page返回的是两个list,一个是当前页面所有的图片地址,第二个是当前页面所有的站内链接。图片不需要判断是否本域名,因为图片一般会用专门的服务器,或者cdn,域名不同是很正常的事情。
接下来是根据页面获取的图片地址,抓取图片保存到本地的模块。
def store_image(save_path, img_url): ''' 将地址为img_url的图片保存到save_path目录下。 ''' img_url_parsed = urllib.parse.urlparse(img_url) try: img_path = save_path+'/'+os.path.dirname(img_url_parsed.path).strip('/').replace('/','_') img_file_path = img_path + '/' + os.path.basename(img_url_parsed.path) img_req = requests.get(img_url, headers=headers) if img_req.status_code != 200: logging.error(img_url+' http code: '+str(img_req.status_code)) return False if len(img_req.content)< 100*1024: logging.warning(img_url+" too small") return True if not os.path.exists(img_path): os.makedirs(img_path) with open(img_file_path,"wb") as fp: fp.write(img_req.content) logging.info("saved "+img_url) except Exception as e: logging.error(img_url+' '+str(e))
函数store_image将图片保存到指定的路径save_path下,如果目录不存在,会自动创建,这里过滤掉了大小在100k以下的图片。这里为了简化,减少了图片的目录深度,原地址里面的路径都会转化为下划线分隔的一个目录,使得多级目录简化为一级。
再加个控制函数就大功告成了。
def site_download(url,save_path): visited_url = {} stored_img = {} to_visit = [url] while len(to_visit)>0: url = to_visit.pop() imgs,urls = process_page(url) visited_url[url]=1 for img in imgs: if img not in stored_img: stored_img[img]=1 store_image(save_path,img) for u in urls: if u not in visited_url: to_visit.append(u)
site_download接收传入的起始地址和图片保存路径,然后递归处理所有页面以及子页面,并判断是否处理过。这里简化了处理,都用map去表示是否访问过,因为一般几十万上百万的页面,应该不会占用太多内存。
加个脚本执行的入口就可以了
if __name__=="__main__": if len(sys.argv) < 3: print("usage: python downloader.py site_url img_path") sys.exit(1) site_download(sys.argv[1],sys.argv[2])
使用方法就是 python downloader.py 网站路径 图片保存路径
好的,早已按捺不住了,赶紧来跑一跑吧。
日志好多,大部分警告和错误都是无用的日志,比如https证书有问题的,网页太久失效的,以及大部分都是图片太小的。
我执行参数里面,图片保存路径是当前目录下的images目录,打开看看。
嗯哼,全部到碗里来了。
注意一点,这种访问方式对服务器负载比较高,有些网站会封掉高频访问的ip的,所以注意在访问时可以适量sleep降低频率。
另外脚本会遍历网站有链接的所有页面,所以比较慢,慢慢等着吧。
最后,本文给出的只是一个抓取网站内容的代码框架,能完成基本工作,但是很简单,没有处理各种可能的异常,没有细致地处理页面。有兴趣的同学可以自己根据需求增加细节完善,比如sleep降频,比如根据网页内容把同一篇文章的图片聚合,比如根据网页结构只抓取其中感兴趣的区域的图片等等。
相关推荐
- 基于Python查找图像中最常见的颜色
-
如果我们能够得知道一幅图像中最多的颜色是什么的话,可以帮助我们解决很多实际问题。例如在农业领域中想确定水果的成熟度,我们可以通过检查水果的颜色是否落在特定范围内,来判断它们是否已经成熟。接下来我们将使...
- 出大要几次/圣彼得堡悖论
-
程序:fromrandomimportrandomdeffn():n=1whilerandom()<0.5:n+=1returnny=[fn()...
- 使用OpenCV测量图像中物体之间的距离
-
原文链接:https://www.pyimagesearch.com/2016/04/04/measuring-distance-between-objects-in-an-image-with-op...
- 让颜色更加饱满和有冲击力:图像颜色校正
-
大家拍照或图片时,获取会遇到图像颜色与实际颜色存在色差的现象。我们看一个标准色卡的图片:第一张图片就是有色差的图片,这种现象一般是相机或光线的原因造成的,我们可以通过标准色卡进行校正。第一张图片是有色...
- Python 数据分析 : 实例
-
1、构建矩阵生成4x4形式的矩阵,矩阵中的数据是1~10之间的随机数random_list=np.random.random(16)random_list=np.round(...
- 用这些免费开源的图标库,为你的项目画龙点睛
-
精致好看的图标能够为你的项目增色不少,今天我就整理了一期图标库精选系列,希望你可以从中找到自己喜欢的图标库。下面就跟我来一场视觉的盛宴,我会一一介绍GitHub上品牌、流行、极小,各具特色的免费精...
- ICON设计规范之图标尺寸
-
编辑导语:图标设计是UI设计中不可缺少的元素,它看似简单,但其实内含门道。本篇文章里,作者就对icon设计的相关知识和icon绘制方法做出经验介绍。如果你对icon设计也想要有所了解的话,那就点进来看...
- PHP开发必备VSCode插件(大全)
-
通用chinese(simplified...):简体中文语言包liveserverhtml:实时预览prettier-codeformatter:最流行的代码格式化插件...
- 增强用户体验:前端开发中HTML5和CSS3表格属性的应用与优化研究
-
摘要:本文探讨了在前端开发中HTML5和CSS3表格属性的应用与优化。首先介绍了HTML5中常用的表格元素和CSS3中丰富的表格样式属性,旨在帮助开发人员定制表格的外观和样式。其次,研究了表格结构的优...
- 产品经理小技术:图片素材随手找,原型设计快又好
-
数十万互联网从业者的共同关注!作者:牛冰峰博客:http://uxfeng.com/画图——这项古老而精细的做法,是一代代产品狗们得以传承的立足之本。草图、线框图、思维导图、PPT插图、数据汇报图表、...
- MAUI Blazor 项目实战 - 从0到1轻松构建多平台应用UI
-
前言最近在项目中尝鲜了MAUI,总体感受下来还是挺不错的,优缺点并存,但是瑕不掩瑜,目前随着.Net版本的迭代升级对它的支持也越来越友好,相信未来可期!感兴趣的朋友欢迎关注。文章中如有不妥的地方,也请...
- webstorm常用的插件
-
1、AtomMaterialIcons推荐原因:这款插件不仅...
- 「智能家居」自动化平台nodered第三方节点dashboard的使用
-
自带节点库讲完了,开始说说第三方节点库dashboard,该库提供另一个可配置的UI页面,可以配置一些表单元素,以及图表。先来看一下别人使用dashboard制作的面板吧,是不是很漂亮。接下来我们一...
- 「炫丽」从0开始做一个WPF+Blazor对话小程序
-
大家好,我是沙漠尽头的狼。...
- MAUI使用Masa blazor组件库
-
上一篇(点击阅读)我们实现了UI在Web端(BlazorServer/Wasm)和客户端(Windows/macOS/Android/iOS)共享,这篇我加上MasaBlazor组件库的引用,并...
你 发表评论:
欢迎- 一周热门
-
-
如何评估预测值与真实值之间的匹配质量
-
如何解决npm安装依赖报错ERESOLVE unable to resolve dependency tree
-
超详细的cmder工具介绍及功能、快捷键说明
-
畅网 N5105 四口 2.5G 小主机安装 WIN10 对比 WIN11 跑分
-
常见面试第三题之Activity的几种启动模式介绍
-
软件推荐丨gocron —— 定时任务管理系统
-
一分钟带你认识了解电信光猫(电信光猫有什么用途)
-
聊聊C++20最大的变革之一 —— Coroutine,看不懂你打我(一)
-
硬核!Rust异步编程方式重大升级:新版Tokio如何提升10倍性能详解
-
Vite 4.0 正式发布(vite版本)
-
- 最近发表
- 标签列表
-
- systemproperties (65)
- npm版本管理 (61)
- localhost:15672 (59)
- materialtheme (86)
- node-ssh (68)
- 图床搭建 (62)
- vue3addeventlistener (60)
- mybatisselectone (78)
- css圆形进度条 (69)
- androidble蓝牙开发 (62)
- android-gif-drawable (60)
- appender-ref (64)
- springbootmockito (68)
- css边框渐变色和圆角 (58)
- gsonfastjson (59)
- 依赖注入的方式 (62)
- cookie跨域共享 (63)
- easyexcel导出图片 (77)
- dp数组 (61)
- js获取兄弟节点 (68)
- sysctl-a (60)
- java知音 (58)
- window.target (62)
- apimodel注解的作用 (60)
- window.onerror (66)