python实现壁纸批量下载代码实例
作者:laozhang 发布时间:2023-11-15 12:38:54
项目地址:https://github.com/jrainlau/wallpaper-downloader
前言
好久没有写文章了,因为最近都在适应新的岗位,以及利用闲暇时间学习python。这篇文章是最近的一个python学习阶段性总结,开发了一个爬虫批量下载某壁纸网站的高清壁纸。
注意:本文所属项目仅用于python学习,严禁作为其他用途使用!
初始化项目
项目使用了virtualenv
来创建一个虚拟环境,避免污染全局。使用pip3
直接下载即可:
pip3 install virtualenv
然后在合适的地方新建一个wallpaper-downloader
目录,使用virtualenv
创建名为venv
的虚拟环境:
virtualenv venv
. venv/bin/activate
接下来创建依赖目录:
echo bs4 lxml requests > requirements.txt
最后yun下载安装依赖即可:
pip3 install -r requirements.txt
分析爬虫工作步骤
为了简单起见,我们直接进入分类为“aero”的壁纸列表页:http://wallpaperswide.com/aer...。
可以看到,这一页里面一共有10张可供下载的壁纸。但是由于这里显示的都是缩略图,作为壁纸来说清晰度是远远不够的,所以我们需要进入壁纸详情页,去找到高清的下载链接。从第一张壁纸点进去,可以看到一个新的页面:
因为我机器是Retina屏幕,所以我打算直接下载体积最大的那个以保证高清(红圈所示体积)。
了解了具体的步骤以后,就是通过开发者工具找到对应的dom节点,提取相应的url即可,这个过程就不再展开了,读者自行尝试即可,下面进入编码部分。
访问页面
新建一个download.py
文件,然后引入两个库:
from bs4 import BeautifulSoup
import requests
接下来,编写一个专门用于访问url,然后返回页面html的函数:
def visit_page(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36'
}
r = requests.get(url, headers = headers)
r.encoding = 'utf-8'
soup = BeautifulSoup(r.text, 'lxml')
return soup
为了防止被网站反爬机制击中,所以我们需要通过在header添加UA把爬虫伪装成正常的浏览器,然后指定utf-8编码,最后返回字符串格式的html。
提取链接
在获取了页面的html以后,就需要提取这个页面壁纸列表所对应的url了:
def get_paper_link(page):
links = page.select('#content > div > ul > li > div > div a')
collect = []
for link in links:
collect.append(link.get('href'))
return collect
这个函数会把列表页所有壁纸详情的url给提取出来。
下载壁纸
有了详情页的地址以后,我们就可以进去挑选合适的size了。在对页面的dom结构分析后可以知道,每一个size都对应着一个链接:
所以第一步,就是把这些size对应的链接提取出来:
wallpaper_source = visit_page(link)
wallpaper_size_links = wallpaper_source.select('#wallpaper-resolutions > a')
size_list = []
for link in wallpaper_size_links:
href = link.get('href')
size_list.append({
'size': eval(link.get_text().replace('x', '*')),
'name': href.replace('/download/', ''),
'url': href
})
size_list
就是这些链接的一个集合。为了方便接下来选出最高清(体积最大)的壁纸,在size
中我使用了eval
方法,直接把这里的5120x3200
给计算出来,作为size
的值。
获取了所有的集合之后,就可以使用max()
方法选出最高清的一项出来了:
biggest_one = max(size_list, key = lambda item: item['size'])
这个biggest_one
当中的url
就是对应size的下载链接,接下来只需要通过requests
库把链接的资源下载下来即可:
result = requests.get(PAGE_DOMAIN + biggest_one['url'])
if result.status_code == 200:
open('wallpapers/' + biggest_one['name'], 'wb').write(result.content)
注意,首先你需要在根目录下创建一个wallpapers
目录,否则运行时会报错。
整理一下,完整的download_wallpaper
函数长这样:
def download_wallpaper(link):
wallpaper_source = visit_page(PAGE_DOMAIN + link)
wallpaper_size_links = wallpaper_source.select('#wallpaper-resolutions > a')
size_list = []
for link in wallpaper_size_links:
href = link.get('href')
size_list.append({
'size': eval(link.get_text().replace('x', '*')),
'name': href.replace('/download/', ''),
'url': href
})
biggest_one = max(size_list, key = lambda item: item['size'])
print('Downloading the ' + str(index + 1) + '/' + str(total) + ' wallpaper: ' + biggest_one['name'])
result = requests.get(PAGE_DOMAIN + biggest_one['url'])
if result.status_code == 200:
open('wallpapers/' + biggest_one['name'], 'wb').write(result.content)
批量运行
上述的步骤仅仅能够下载第一个壁纸列表页的第一张壁纸。如果我们想下载多个列表页的全部壁纸,我们就需要循环调用这些方法。首先我们定义几个常量:
import sys
if len(sys.argv) != 4:
print('3 arguments were required but only find ' + str(len(sys.argv) - 1) + '!')
exit()
category = sys.argv[1]
try:
page_start = [int(sys.argv[2])]
page_end = int(sys.argv[3])
except:
print('The second and third arguments must be a number but not a string!')
exit()
这里通过获取命令行参数,指定了三个常量category
, page_start
和page_end
,分别对应着壁纸分类,起始页页码,终止页页码。
为了方便起见,再定义两个url相关的常量:
PAGE_DOMAIN = 'http://wallpaperswide.com'
PAGE_URL = 'http://wallpaperswide.com/' + category + '-desktop-wallpapers/page/'
接下来就可以愉快地进行批量操作了,在此之前我们来定义一个start()
启动函数:
def start():
if page_start[0] <= page_end:
print('Preparing to download the ' + str(page_start[0]) + ' page of all the "' + category + '" wallpapers...')
PAGE_SOURCE = visit_page(PAGE_URL + str(page_start[0]))
WALLPAPER_LINKS = get_paper_link(PAGE_SOURCE)
page_start[0] = page_start[0] + 1
for index, link in enumerate(WALLPAPER_LINKS):
download_wallpaper(link, index, len(WALLPAPER_LINKS), start)
然后把之前的download_wallpaper
函数再改写一下:
def download_wallpaper(link, index, total, callback):
wallpaper_source = visit_page(PAGE_DOMAIN + link)
wallpaper_size_links = wallpaper_source.select('#wallpaper-resolutions > a')
size_list = []
for link in wallpaper_size_links:
href = link.get('href')
size_list.append({
'size': eval(link.get_text().replace('x', '*')),
'name': href.replace('/download/', ''),
'url': href
})
biggest_one = max(size_list, key = lambda item: item['size'])
print('Downloading the ' + str(index + 1) + '/' + str(total) + ' wallpaper: ' + biggest_one['name'])
result = requests.get(PAGE_DOMAIN + biggest_one['url'])
if result.status_code == 200:
open('wallpapers/' + biggest_one['name'], 'wb').write(result.content)
if index + 1 == total:
print('Download completed!\n\n')
callback()
最后指定一下启动规则:
if __name__ == '__main__':
start()
运行项目
在命令行输入如下代码开始测试:
python3 download.py aero 1 2
然后可以看到下列输出:
拿charles抓一下包,可以看到正在脚本正在平稳地运行中:
此时,下载脚本已经开发完毕,终于不用担心壁纸荒啦!
来源:https://segmentfault.com/a/1190000012978490


猜你喜欢
- 1.问题背景Python之所以强大,不仅是因为该语言本身的特点,也是因为它拥有众多无所不能的第三方库。强大的软件库允许开发者专注于业务,避免
- 前言在了解了REST farmwork封装的视图类之后,我对python的面向对象有了更深刻的理解。Django RESR framewor
- MaxDB和MySQL是独立的数据库管理服务器。系统间的协同性是可能的,通过相应的方式,系统能够彼此交换数据。要想在MaxDB和MySQL之
- transpose() 这个函数如果括号内不带参数,就相当于转置,和.T效果一样,而今天主要来讲解其带参数。我们看如下一个numpy的数组:
- 一、为什么要配置文件1、容易编辑,配置比较集中,方便修改,在大业务量的系统里面,通过配置会方便后人理解整个系统的架构2、做到业务代码和环境解
- 最近从某网站下载了一批文档,但是文件是用数字串命名的文档(很多图书馆都这样吧),现在我也下载完了这些文件,也有这些文件的列表,就是不能一个一
- Tuple 叫做 tuple,用小括号、或者无括号来表述,是一连串有顺序的数字。a_tuple = (12, 3, 5, 15 , 6)an
- 原则, 以datetime为中心, 起点或中转, 转化为目标对象, 涵盖了大多数业务场景中需要的日期转换处理步骤:1. 掌握几种对象及其关系
- 本文内容会引起杀毒软件的莫名兴奋,建议先安抚杀毒软件,让杀毒软件先休息一下再继续操作安装python3.6转exe会遇到很多问题,其中部分是
- 1. 介绍-- PHP5添加了一项新的功能:Reflection。这个功能使得phper可以reverse-engineer class,
- 我也一一试过,结果是:中文乱码问题没解决,mysql服务却不能启动了, 汗颜了,还是自己动手解决吧,我这里也截图了,方便参观。我用的是app
- 前言首先回顾一下什么是事务,事务是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么
- 前言需求: 必须现在需要动态创建16个list,每个list的名字不一样,但是是有规律可循,比如第一个list的名字叫:arriage_li
- 先给大家介绍下python中format函数,在文章下面给大家介绍python.format()函数的简单使用---恢复内容开始---pyt
- 工作需要开始学Perl,下载个Window版(5.16)的: 下载链接 http://www.activestate.com/activep
- 测试的php文件 <?php $link=mysql_connect('localhost','root
- 概述:each() 方法规定为每个匹配元素规定运行的函数。返回 false 可用于及早停止循环,相当于break。返回 true 可以结束本
- 本人自己写过三个图片轮播,一个是简单的原生JS实现的,没有什么动画效果的,一个是结合JQuery实现的,淡入淡出切换的。现在想做一个酷一点的
- 一、前言 前面我们学习了if分支判断和for循环语句,在这次推送中我们将继续了解循环大家庭的成员们。大家可以通过上面的流程图来了解
- 在操作过程中,两表查询都没有问题,但是三表查询就开始出现问题有以下三张表,分表为pl表(uid,content),user表(id,user