70行python代码实现壁纸批量下载

项目地址:https://github.com/jrainlau/w...html

前言

很久没有写文章了,由于最近都在适应新的岗位,以及利用闲暇时间学习python。这篇文章是最近的一个python学习阶段性总结,开发了一个爬虫批量下载某壁纸网站的高清壁纸。python

注意:本文所属项目仅用于python学习,严禁做为其余用途使用!

初始化项目

项目使用了virtualenv来建立一个虚拟环境,避免污染全局。使用pip3直接下载便可:git

pip3 install virtualenv

而后在合适的地方新建一个wallpaper-downloader目录,使用virtualenv建立名为venv的虚拟环境:github

virtualenv venv

. venv/bin/activate

接下来建立依赖目录:浏览器

echo bs4 lxml requests > requirements.txt

最后yun下载安装依赖便可:dom

pip3 install -r requirements.txt

分析爬虫工做步骤

为了简单起见,咱们直接进入分类为“aero”的壁纸列表页:http://wallpaperswide.com/aer...ide

clipboard.png

能够看到,这一页里面一共有10张可供下载的壁纸。可是因为这里显示的都是缩略图,做为壁纸来讲清晰度是远远不够的,因此咱们须要进入壁纸详情页,去找到高清的下载连接。从第一张壁纸点进去,能够看到一个新的页面:函数

clipboard.png

由于我机器是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'
    return BeautifulSoup(r.text, 'lxml')

为了防止被网站反爬机制击中,因此咱们须要经过在header添加UA把爬虫假装成正常的浏览器,而后指定utf-8编码,最后返回字符串格式的html。

提取连接

在获取了页面的html之后,就须要提取这个页面壁纸列表所对应的url了:

def get_paper_link(page):
    links = page.select('#content > div > ul > li > div > div a')
    return [link.get('href') for link in links]

这个函数会把列表页全部壁纸详情的url给提取出来。

下载壁纸

有了详情页的地址之后,咱们就能够进去挑选合适的size了。在对页面的dom结构分析后能够知道,每个size都对应着一个连接:

clipboard.png

因此第一步,就是把这些size对应的连接提取出来:

wallpaper_source = visit_page(link)
wallpaper_size_links = wallpaper_source.select('#wallpaper-resolutions > a')
size_list = [{
    'size': eval(link.get_text().replace('x', '*')),
    'name': link.get('href').replace('/download/', ''),
    'url': link.get('href')
} for link in wallpaper_size_links]

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 = [{
        'size': eval(link.get_text().replace('x', '*')),
        'name': link.get('href').replace('/download/', ''),
        'url': link.get('href')
    } for link in wallpaper_size_links]

    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_startpage_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 = [{
        'size': eval(link.get_text().replace('x', '*')),
        'name': link.get('href').replace('/download/', ''),
        'url': link.get('href')
    } for link in wallpaper_size_links]

    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

而后能够看到下列输出:

clipboard.png

拿charles抓一下包,能够看到脚本正在平稳地运行中:

clipboard.png

此时,下载脚本已经开发完毕,终于不用担忧壁纸荒啦!

相关文章
相关标签/搜索