欢迎加入我们卧虎藏龙的python讨论qq群:996113038
┉┉┉┉┉┉ 『导语』 ┉┉┉┉┉┉
尽管每次都只是匆匆一眼
但它仍然能影响一天的心情
它就是我们的桌面壁纸
时常更换壁纸能带来一种新鲜感
在繁复的工作学习中带来一丝亮点
什么?你是选择困难症?每次都挑很久?
又什么?你懒得手动切换?
别担心,今天笔者就带你用python
获取好看壁纸并实现桌面自动换壁纸
温馨提示
本文过程灰常详细
阅读时间可能较长~
¨¨¨『代码及相关资源获取』¨¨¨
1:关注“python趣味爱好者”公众号,回复“s1”获取源代码。
2:加入群聊:996113038。在群文件中下载源代码以及相关资料。
效果演示:
怎么样,是不是很酷炫?
接下来就一起来看看我们是怎样做到的吧
开发工具:
python3.7.6
相关第三方库:
time
requests
lxml
urllib
基本原理:
之前已经有了许多的爬虫推文了。相信大家对于爬虫的原理已经不再陌生了,无非就是获取网页源代码,提取目标信息,本地保存。我们今天这个也是如此,只不过一些细节部分需要稍加注意~
目标网址:
http://www.netbian.com/
往期精选:
python爬虫批量下载“简谱”
python爬取WHO全球疫情数据
讲解部分:
1、获取网页源代码
因为本次目标网页的壁纸数量有点大,约有两万多张,所以如果我们要全部爬下来的话,返爬措施要做好,所以我们先来获取用于伪装的Headers。这里以Chorm浏览器作示范,其他浏览大同小异。
首先,在网页随意位置右键,选择最下面的检查
第一步:点击Network。点击后你就会左下角看到如图许多网页加载的东西。
第二步:选择框内的任意一条(不局限于红框之内),右边就会显示很多信息。
第三步:将显示的信息下拉到最下面,会看到 Requests Headers 的信息框,里面有 Referer 和 User-Agent 信息,这就是我们一会儿要用到的伪装。
注意:
1、如果你在第一步没有看到如图的许多的东西,那就需要手动将网页重新加载一下,快捷键:Ctrk+R。
2、第三步如果没有看见 Referer ,那就是第二步选择选择的时候选择错了,需要重新选择一个有 Referer 的。
获取到的 Requests Headers 的信息如下:
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Safari/537.36",
"Referer": "http://www.netbian.com/"
}
我们已经获取到了伪装信息了,接下来当然就是获取网页源代码咯~
方法很简单,代码如下:
import requests
import time
start_url = http://www.netbian.com
html = requests.get(start_url, headers, timeout=3)
time.sleep(1)
content = html.content.decode("utf-8")
第一行代码为导入 requests 模块;
第四行代码为向目标网址发起请求,参数 headers 作用为伪装爬虫,timeouot 参数为链接超时时间,请求超过这个时间就会报错。
第五行代码为程序睡一秒,用来防止返爬。
第六行代码为对获取网页代码进行解码。
当然,如果你是这么请求网页源代码的,对于一般的网页兴许可以,但是,在这个网页不行!报错如下:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd7 in position 60: invalid continuation byte
错误的大概意思就是"utf-8"无法解码某些字符,因此在 decode() 方法里面需要加上一个参数来忽略这些无法解码的特殊字符,加上后如下:
content = html.content.decode("utf-8", errors="ignore")
到这里我们就已经把网页的源代码储存到了 content 里面。如果你不放心的话还可以打印一下本次请求的状态码:
print(html.status_code)
2、获取壁纸的下载地址
第一步:点击如图所示按钮。
第二步:随便点一张图片。
第三步:右边已经显示了我们点击图纸的下载地址了。
获取图片下载链接的方法非常简单:
from lxml import etree
html = etree.HTML(content)
url_list = html.xpath('//div[@class="list"]/ul//img/@src')
第一行代码为导入 lxml 模块中的 etree。
第二行代码为使用 xpath 方法获取目标信息的固定用法,记住就好~实在想知道为什么就自己去官网找~
第三行代码就是从网页源代码中提取到这一页的所有满足条件的图片的下载地址。
注意:关于 xpath 的用法由于文章篇幅的原因就不多加赘述了,想要学习的同学可以自己找一些视频看看,或者如果大家有需求可以下次发一篇关于 xpath 简单用法的推文给大家。
3、下载图片并保存到指定文件夹
或许在大家平时的爬取方法中都需要先请求图片地址,打开文件,写入文件,关闭文件等等这么多的步骤来下载一张图片,不不不,根本不需要这么麻烦~~其实只要两行代码就可以下载图片到指定的文件:
import urllib.request
urllib.request.urlretrieve(url, r"./img2/" + img_name)
当然,我们上一步获取到的是一个 url 列表,因此此处需要一个循环来完成对每个 url 地址的下载:
import urllib.request
for url in url_list:
img_name = url[-15:-4] + ".jpg"
urllib.request.urlretrieve(url, r"./img/" + img_name)
这里我们取每一个图片 url 地址的倒数第 5 个字符到倒数第 15 个字符来对图片进行命名,因此就多加了一行代码。
至此,我们第一页的图片就已经下载完成了(记得自己创建一个 img 的文件夹哦,否则报错。),你可以去你的 img 文件夹中看看,18 张好看的壁纸已经乖乖的躺在里面了。此处,为了保证每一个图片名字的唯一性,在最后代码重构的时候会对图片的名字进行其他的处理:设置一个变量用于记录下载图片的数量,然后将这个数字加入图片的命名中,这样就保证了图片名字的唯一性。
但是!我们的目标仅仅只是这一页吗?当然不,我们的目标是把这个网址的壁纸统统的下下来放在后宫指定文件夹里面。所以,我们的下一步就是得到下一页网页的 url 地址。
4、获取下一页网页的 url 地址
我们把网页往下拉,会发现最下面有一连串的页码以及上一页和下一页,因此,我们获取下一页的方式有两种:
第一种就是知道网页一共的页数,然后设置一个变量来记录下一页该下载的页数,这一种比较简单,就是每获取完一页的图片 url 地址后,就把变量加个 1 ,这样就可以一直获取下去了。但是这样会有个问题,当你获取到最后一页的时候怎么办?那时候这个网址就没有了下一页,如果你还去请求,那么程序就会报错,作为一个完美主义者,怎么可以允许这种情况出现呢!因此我们就有了第二种方法。
第二种方法就是获取本页的下一页那个按钮的地址,我们获取到它不就是直接获取到了下一页的地址了吗,而且还不用设个变量来计数。
下面我就将两种方法都介绍一下:
第一种:
首先我们先来看看第二页第三页和初始页面的 url 地址的区别:
http://www.netbian.com
http://www.netbian.com/index_2.htm
http://www.netbian.com/index_3.htm
从上面我们可以清楚的看出第二页比第一页多了 index_2.htm,第三页和第二页的差别就是差了个数字而已,所以我们构造下一页的 url 地址的方法为在初始地址上加上 index_{}.htm,然后设置一个变量记录下一页的数字,最后通过 format() 方法把实际页数加进去。如下:
next_url = start_url + "/index_{}.htm".format(page)
其中 page 即为记录页数的变量。
第二种:
直接采用 xpath 方法获取到下一页的 url 地址。如图:
但是我们发现,下一页的 url 地址只有一截,即:/index_2.htm 所以还需要再次构造一下。上面我们说了,xpath 方法获取到的信息为列表格式,所以在后面要加一个索引来变成字符串。代码如下:
next_url = html.xpath('//div[@class="page"]/a[@class="prev"]/@href')[0]
next_url = start_url + next_url
注意:在这个地方,笔者遇到了一个很大很大的坑,先放张图上来让大家看看,能不能找到这个坑~
是的没错!以第四页为例,上一页和下一页的标签以及 class 类型是一样的!!!也就意味着当你请求的第二页的时候你用上述方法获得的url 地址是第一页的!!!然后再到第二页,再到第一页......笔者未发现这个问题之前用这个爬虫在这个网站下载了 5 万余张图片...就很纳闷,它一共就 2 万余张,怎么会下了 5 万多次...后面发现,原来是我对第一页和第二页的图片下了 5 万余次......所以这里的代码要改成:
next_url = html.xpath('//div[@class="page"]/a[@class="prev"]/@href')[1] # 修改的地方是最后这个 1
next_url = start_url + next_url
修改之后...
获取到下一页的 url 地址后,即可以通过一个循环来遍历这个网址的所有页面了,从而获取到所有图片的 url 地址,进而全部下载下来,哈哈哈,是不是很开心~
5、代码重构并增加容错率
为什么要增加容错率呢,因为每个人都会希望程序一启动,一直到结束它都不会出问题,所以就需要对一些容易报错的地方进行修改,以增加其容错率。
(1)实时改变 Referer。
在获取到下一页的 url 地址后,就可以对 Referer 进行修改了。代码如下:
headers["Referer"] = url
或许会有小伙伴要问了,这个是什么呀?为什么要改它?
Referer 这个参数呢,大概意思就是记录了你是从哪个网址过来的,作用呢,当然就是防止返爬咯,因为有些网址就会检查这个参数,如果你没有,它就很有可能识别出你是个爬虫~我们要打造一个将它整个网站的图片都下载下来的爬虫,就要尽可能的保证爬虫不被识别。
(2)判断状态码
大家都知道,200 才表示着你请求这个网址成功了(当然也有意外),所以为了给我们爬虫进行的过程中不报错再加一层保险,我们对请求网页源码的那段代码进行修改:
while url:
html = requests.get(url, self.headers, timeout=3)
time.sleep(1)
code = html.status_code
if code != 200:
print("哎呀,状态码怎么变成{}了呀,那就先休息10秒吧~~".format(code))
time.sleep(10)
continue
content = html.content.decode("utf-8", errors="ignore")
这里用一个 while 循环来增加这层保险,就是当返回的状态码不是 200 时,会让爬虫休息 10 秒,然后再重新对目前的网址进行请求。只要 url 地址有值,就会一直对这个 url 地址进行请求,直到状态码为 200。
(3)防止最后一页无法请求到下一页的 url 地址而报错
采用 try 方法对获取下一页 url 地址的代码进行包装,让它最后一页无法请求下一页的时候捕获返回的错误,然后将下一页的 url 赋值为 False。从而让爬虫判断出已经没有下一页了,最后程序结束。代码如下:
try:
# next_url = html.xpath('//div[@class="page"]/a[@class="prev"]/@href')
next_url = self.start_url + "/index_{}.htm".format(self.page)
return next_url
except ValueError:
return False
最终重构的代码如下,供大家参考:
import time
import requests
from lxml import etree
import urllib.request
class Spider(object):
def __init__(self):
self.start_url = "http://www.netbian.com"
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/80.0.3987.162 Safari/537.36",
"Referer": self.start_url
}
self.num = 0
self.page = 1
def get_response(self, url):
while url:
# ip = self.ip_list[self.num] proxies={'http': ip}
html = requests.get(url, self.headers, timeout=3)
time.sleep(1)
code = html.status_code
if code != 200:
print("哎呀,状态码怎么变成{}了呀,那就先休息10秒吧~~".format(code))
time.sleep(10)
continue
content = html.content.decode("utf-8", errors="ignore")
return content
def get_url_list(self, content):
html = etree.HTML(content)
url_list = html.xpath('//div[@class="list"]/ul//img/@src')
print("成功获取第{}页图片链接".format(self.page))
self.page += 1
return url_list
def download_img(self, url_list):
for url in url_list:
img_name = url[-15:-4] + str(self.num) + ".jpg"
urllib.request.urlretrieve(url, r"./img2/" + img_name)
self.num += 1
print("成功保存第{}张图片:{}".format(self.num, img_name))
def __get_next_url(self, content):
html = etree.HTML(content)
try:
# next_url = html.xpath('//div[@class="page"]/a[@class="prev"]/@href')
next_url = self.start_url + "/index_{}.htm".format(self.page)
return next_url
except ValueError:
return False
def run(self):
url = self.start_url
while url:
content = self.get_response(url)
url_list = self.get_url_list(content)
self.download_img(url_list)
self.headers["Referer"] = url
url = self.__get_next_url(content)
if __name__ == '__main__':
img = Spider()
img.run()
关于爬取壁纸的爬虫讲解就到这里结束了,接下来就是设置自动更换壁纸的时候了,毕竟爬了这么多壁纸,不能拿出来用多浪费呀。
以下以 Windows 10 为例:
第一步:打开系统设置,点击个性化。
第二步:点击左侧背景,再右侧背景选项框中选择幻灯片放映,然后点击下面的浏览按钮,选择你下载好壁纸的文件夹。
第三步:其他设置,图片切换频率,是否无序播放等等,这个就看你自己的爱好啦。
生活就像一盒巧克力
你永远不知道下一秒会得到什么
就像你也不知道下一秒你的壁纸会给你带来怎样的惊喜
本期分享到此结束啦
很高兴你能看到最后
作者|十丿叶
编辑|潇洒哥
感谢大家观看
有钱的老板可以打赏一下小编哦!
扫描下方二维码,关注公众号
参考资料:
图片来源:
彼岸桌面壁纸
http://www.netbian.com/