您当前的位置:首页 > 计算机 > 编程开发 > Python

python爬虫爬取Wallhaven每日Top壁纸(附进度条)

时间:12-19来源:作者:点击数:

Wallhaven这个壁纸网站想必都耳熟能详,它的壁纸链接都直接放在网页里,可以说是非常友好

用BeautifulSoup4查找元素的过程不方便展示,也解释不清,所以直接上代码了,各位可以尝试看看源码来了解全过程

本人也是新手,所以不会仔细讲解编写过程和进度条的实现,更多是为了记录,所以请各位大佬手下留情~~~

一、分析小壁纸源码

了解这个网站的人应该都知道每日Top壁纸的位置,这里可以用这个URL直接打开:https://wallhaven.cc/search?categories=110&purity=100&topRange=1d&sorting=toplist&order=desc

进入页面后,右键检查第一张用于展示的小壁纸,可以很清楚的看到他的源码(这里我就直接上源码了)

<figure class="thumb thumb-6dkqxx thumb-sfw thumb-anime" data-wallpaper-id="6dkqxx" style="width:300px;height:200px">
        <img alt="loading" class="lazyload loaded" data-src="https://th.wallhaven.cc/small/6d/6dkqxx.jpg" src="https://th.wallhaven.cc/small/6d/6dkqxx.jpg">
        <a class="preview"  target="_blank"></a>
        <div class="thumb-info">
                <span class="wall-res">6792 x 9600</span>
                <a class="jsAnchor overlay-anchor wall-favs" data->50<i class="fa fa-fw fa-star"></i>
                </a>
                <a class="jsAnchor thumb-tags-toggle tagged" data- original-title="Tags">
                        <i class="fas fa-fw fa-tags"></i>
                </a>
        </div>
</figure>

不难看出,小壁纸的链接是:https://th.wallhaven.cc/small/6d/6dkqxx.jpg

其中,6d6dkqxx是两个关键部分,就如同该壁纸的ID一样

所以这里我们可以用split()来分割提取出这两个数据,留着之后使用

datas = url.split('/') #datas[4]是6d,datas[5]是6dkqxx.jpg

二、分析原图源码

接下来,我们点击小壁纸进入该壁纸的单独页面,之后还是老样子,右键检查原图,可以找到以下源码

<img id="wallpaper" src="https://w.wallhaven.cc/full/6d/wallhaven-6dkqxx.jpg" alt="Anime 6792x9600 anime girls violin Azur Lane Seattle (Azur Lane) purple dress gray hair pink eyes short hair purple pantyhose musical instrument big boobs no bra sitting legs together ahoge dress" data-wallpaper-id="6dkqxx" data-wallpaper-width="6792" data-wallpaper-height="9600" crossorigin="anonymous" class="fill-horizontal">

原图的链接被毫不遮掩地直接放在该页面的一个img标签里,这对于新手来说真是太友好

通过对比上文的小壁纸源码,我们可以发现原图的链接存在一个模板:'https://w.wallhaven.cc/full/'+ 第一关键部分 +'/wallhaven-'+ 第二关键部分 +'.jpg'

而这两个关键部分我们已经提取出来了,只需要用format()方法组装上去即可

url = f'https://w.wallhaven.cc/full/{datas[4]}/wallhaven-{datas[5].split(".")[0]}.jpg'

三、判断图片格式

没错,壁纸的图片格式不止一种!除了jpg,还有png。我也是掉过一次坑才知道

但问题不大,我们将鼠标悬停在图片上即可查看图片格式(只有png格式才会显示)。我们挑一张png格式的壁纸,还是像前面一样右键检查小壁纸的源码,将折叠全部展开,可以看到以下部分

<figure class="thumb thumb-kxw9o1 thumb-sfw thumb-general" data-wallpaper-id="kxw9o1" style="width:300px;height:200px">
        <img alt="loading" class="lazyload loaded" data-src="https://th.wallhaven.cc/small/kx/kxw9o1.jpg" src="https://th.wallhaven.cc/small/kx/kxw9o1.jpg">
        <a class="preview"  target="_blank"></a>
        <div class="thumb-info">
                <span class="wall-res">2304 x 1536</span>
                <a class="jsAnchor overlay-anchor wall-favs" data->43<i class="fa fa-fw fa-star"></i>
                </a>
                <span class="png">
                        <span>PNG</span>
                </span>
                <a class="jsAnchor thumb-tags-toggle tagged" data- original-title="Tags">
                        <i class="fas fa-fw fa-tags"></i>
                </a>
        </div>
</figure>

经过仔细观察,可以看到png格式的壁纸相比于jpg多出来一个span标签

所以我们在用bs4查找时,只需要判断一下该壁纸是否具有span标签就能判断图片格式(我这里查找的是span标签里的PNG文本,不过都一样)

if(each.find('span',class_='png') == None): #判断图片格式,并组装下载链接
            url = f'https://w.wallhaven.cc/full/{datas[4]}/wallhaven-{datas[5].split(".")[0]}.jpg'
        else:
            url = f'https://w.wallhaven.cc/full/{datas[4]}/wallhaven-{datas[5].split(".")[0]}.png'

四、编写代码

前面已经说过了,不方便仔细讲解bs4库的使用,省略了部分查找过程,只讲关键部分,不懂的可以自行搜索了解一下,反正以后都要学

至于进度条的实现,涉及与爬虫相关不太大的tqdm库,这是一个快速、扩展性强的进度条工具库,感兴趣的也可以自行搜索

注意确保导入的库都已安装,把源码保存成py文件,然后直接点击运行或在编辑器(不要用IDLE)中运行即可自动爬取壁纸(个人推荐直接点击运行)

源码如下:

import requests,bs4,os,time,tqdm
#卡住了就随便摁一下键盘,要是还没反应就重连一下网络,然后等待几分钟
 
#请求头,建议修改为自己的浏览器头部
headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35'}
 
#壁纸存放路径,不存在则创建,可以自行修改
date = time.strftime('%Y-%m-%d',time.localtime()) #获取今日日期
path = f"D:\\Downloads\\Wallpapers\\{date}\\"
if not os.path.exists(path):
    os.makedirs(path)
 
all_size = 0
print('正在获取数据,请稍候...(若长时间未响应,请重新启动)',end='\r')
 
#获取今日Top壁纸总页数
res = requests.get('https://wallhaven.cc/search?categories=110&purity=100&topRange=1d&sorting=toplist&order=desc&page=5',headers=headers)
soup = bs4.BeautifulSoup(res.text,'html.parser')
page = int(soup.find('div',id='thumbs').section.header.h2.text.split('/ ')[1])
 
for I in range(page):
    print(f' —————————————————————————————————————————————————————————\n                  正在下载 | 第{I+1}页/共{page}页\n —————————————————————————————————————————————————————————')
 
    #解析网页源码,查找壁纸
    res = requests.get(f'https://wallhaven.cc/search?categories=110&purity=100&topRange=1d&sorting=toplist&order=desc&page={I+1}',headers=headers)
    soup = bs4.BeautifulSoup(res.text,'html.parser')
    images = soup.find_all('figure')
    i = 0
 
    #分别对每张壁纸进行查找链接
    for each in images:
        i += 1
        datas = each.img['data-src'].split('/') #分割关键数据
        if(each.find('span',class_='png') == None): #判断图片格式,并组装下载链接
            url = f'https://w.wallhaven.cc/full/{datas[4]}/wallhaven-{datas[5].split(".")[0]}.jpg'
        else:
            url = f'https://w.wallhaven.cc/full/{datas[4]}/wallhaven-{datas[5].split(".")[0]}.png'
 
        #下载壁纸(附进度条)
        name = url.split('-')[1]
        image = requests.get(url,stream=True,headers=headers)
        file_size = int(image.headers['Content-length'])
        all_size += file_size #统计文件大小
        pbar = tqdm.tqdm(total=file_size,initial=0,unit='B',unit_scale=True,desc='(%02d/%02d)正在下载 | %s | '%(i,len(images),name))
        with open(path + name,'wb') as f:
            for chunk in image.iter_content(chunk_size=1024):
                if chunk:
                    f.write(chunk)
                    pbar.update(1024)
        pbar.close()
 
#下载完毕
print(' —————————————————————————————————————————————————————————\n                   下载完成,共计%.2fMB\n'%(all_size/1024/1024))
input()

PS.如果直接点击后,黑窗口一闪而过,那多半是报错了,建议你放到编辑器中查看报错信息,然后自行修改即可。只要网络正常,报错基本不会太离谱

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门