介绍

    python基于selenium2中的webdriver以及pywin32模块,定时从指定网站随机下载壁纸,然后更新桌面壁纸的实现。

代码

    首先定义一个基于selenium的webdriver的无UI的Chrome浏览器对象,–headless参数定义为无界面,–disable-gpu关闭gpu是为了解决chrome卡的bug。

def __init__(self, url):
        self.url = url
        self.isFirst = True
        options = Options()
        options.add_argument('--headless')
        options.add_argument('--disable-gpu')
        self.driver = webdriver.Chrome(chrome_options=options)

    然后就是要去指定网站随机获取图。在这里,使用set_page_load_timeout函数设置页面加载超时为30秒,如果30秒加载没有完成,则直接超时退出。第一次加载页面,使用get函数来加载,当已经加载过以后,则直接用refresh函数刷新页面即可。WebDriverWaituntil组合使用表示,最多等待10秒,直接到页面找到指定元素才返回,如果超时10秒还没有找到指定元素,则抛出TimeoutException异常,如果页面加载完成还没有找到指定元素则抛出NoSuchElementException异常。find_element_by_xpath用来查找页面中的指定元素,get_attribute函数是获取当前元素指定属性的值。

def run(self):
        self.driver.set_page_load_timeout(30)
        if self.isFirst:
            self.driver.get(self.url)
            self.isFirst = False
        else:
            self.driver.refresh()

        print(self.driver.title)
        try:
            link = WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located(
                    (By.XPATH,
                        '//*[@id="thumbs"]/section[1]/ul/li[1]/figure/a'))
            )

            print(link.get_attribute('href'))
            self.driver.get(link.get_attribute('href'))
            print(self.driver.title)
            img = self.driver.find_element_by_xpath('//*[@id="wallpaper"]')
            print(img.get_attribute('src'))
            self.download(img.get_attribute('src'))
        except TimeoutException:
            traceback.print_exc()
            pass
        except NoSuchElementException:
            traceback.print_exc()
            pass

    使用requests模块的get函数下载图片,当返回的status_code等于200表示成功,其它表示失败。下载成功以后,把图片写入程序工作目录的desktop目录下,没有则创建。

def download(self, imageUrl):
        res = requests.get(imageUrl)
        if (res.status_code == 200):
            currentPath = os.getcwd()
            desktopPath = os.path.join(currentPath, 'desktop')
            if (not os.path.exists(desktopPath)):
                os.mkdir(desktopPath)
            filename = imageUrl.rsplit('/')[-1]
            fpath = os.path.join(desktopPath, filename)
            print(fpath)
            with open(fpath, "wb+") as f:
                f.write(res.content)
            self.jpgToBmp(fpath)
        else:
            print('status_code = %d' % res.status_code)

    最后则是把下载的图片设置成桌面壁纸,这里用到了pywin32模块。直接操作注册表,设置桌面壁纸的样式,然后调用SystemParametersInfo函数设置桌面壁纸并更新桌面,壁纸则设置完成。

def setWallpaper(self, img):
        regKey = win32api.RegOpenKeyEx(
            win32con.HKEY_CURRENT_USER, "Control Panel\\Desktop",
            0, win32con.KEY_SET_VALUE)
        # 0=居中 1=平铺 2=拉伸
        win32api.RegSetValueEx(regKey, "WallpaperStyle",
                               0, win32con.REG_SZ, "2")
        # 0=居中 1=平铺 2=拉伸
        win32api.RegSetValueEx(regKey, "TileWallpaper",
                               0, win32con.REG_SZ, "0")
        win32api.RegCloseKey(regKey)
        # 设置桌面壁纸并更新
        win32gui.SystemParametersInfo(
            win32con.SPI_SETDESKWALLPAPER, img, win32con.SPIF_SENDWININICHANGE)

    Note:早期系统不支持jpg文件设置成桌面壁纸,所以在这里使用Image模块把jpg文件转换成bmp位图,再把转换以后的图片设置成壁纸。在转换之前,先把之前转换的bmp位图都删除,防止占用硬盘空间(当然你的硬盘大就无所谓了)。

def deleteBmpFile(self, path):
        for name in os.listdir(path):
            filePath = os.path.join(path, name)
            if (filePath.endswith(".bmp")):
                os.remove(filePath)

    def jpgToBmp(self, img):
        imgDir = os.path.dirname(img)
        self.deleteBmpFile(imgDir)
        jpgImage = Image.open(img)
        fileName = img.split('\\')[-1]
        prefixName = fileName.split('.')[0]
        bmpFilename = prefixName + '.bmp'
        bmpImage = os.path.join(imgDir, bmpFilename)
        jpgImage.save(bmpImage, "BMP")
        self.setWallpaper(bmpImage)

    完整代码如下,这里的实现设置成每10分钟从网站下载一次图片设置成桌面壁纸并循环处理,同时并没有删除每次下载的jpg图片,只是删除了bmp位图。

# -*- coding: utf-8 -*-
import os
import time
import traceback

import requests
import win32con
from PIL import Image

import win32api
import win32gui
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException, TimeoutException
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


class WallPaper:
    def __init__(self, url):
        self.url = url
        self.isFirst = True
        options = Options()
        options.add_argument('--headless')
        options.add_argument('--disable-gpu')
        self.driver = webdriver.Chrome(chrome_options=options)

    def deleteBmpFile(self, path):
        for name in os.listdir(path):
            filePath = os.path.join(path, name)
            if (filePath.endswith(".bmp")):
                os.remove(filePath)

    def jpgToBmp(self, img):
        imgDir = os.path.dirname(img)
        self.deleteBmpFile(imgDir)
        jpgImage = Image.open(img)
        fileName = img.split('\\')[-1]
        prefixName = fileName.split('.')[0]
        bmpFilename = prefixName + '.bmp'
        bmpImage = os.path.join(imgDir, bmpFilename)
        jpgImage.save(bmpImage, "BMP")
        self.setWallpaper(bmpImage)

    def setWallpaper(self, img):
        regKey = win32api.RegOpenKeyEx(
            win32con.HKEY_CURRENT_USER, "Control Panel\\Desktop",
            0, win32con.KEY_SET_VALUE)
        # 0=居中 1=平铺 2=拉伸
        win32api.RegSetValueEx(regKey, "WallpaperStyle",
                               0, win32con.REG_SZ, "2")
        # 0=居中 1=平铺 2=拉伸
        win32api.RegSetValueEx(regKey, "TileWallpaper",
                               0, win32con.REG_SZ, "0")
        win32api.RegCloseKey(regKey)
        # 设置桌面壁纸并更新
        win32gui.SystemParametersInfo(
            win32con.SPI_SETDESKWALLPAPER, img, win32con.SPIF_SENDWININICHANGE)

    def download(self, imageUrl):
        res = requests.get(imageUrl)
        if (res.status_code == 200):
            currentPath = os.getcwd()
            desktopPath = os.path.join(currentPath, 'desktop')
            if (not os.path.exists(desktopPath)):
                os.mkdir(desktopPath)
            filename = imageUrl.rsplit('/')[-1]
            fpath = os.path.join(desktopPath, filename)
            print(fpath)
            with open(fpath, "wb+") as f:
                f.write(res.content)
            self.jpgToBmp(fpath)
        else:
            print('status_code = %d' % res.status_code)

    def run(self):
        self.driver.set_page_load_timeout(30)
        if self.isFirst:
            self.driver.get(self.url)
            self.isFirst = False
        else:
            self.driver.refresh()

        print(self.driver.title)
        try:
            link = WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located(
                    (By.XPATH,
                        '//*[@id="thumbs"]/section[1]/ul/li[1]/figure/a'))
            )

            print(link.get_attribute('href'))
            self.driver.get(link.get_attribute('href'))
            print(self.driver.title)
            img = self.driver.find_element_by_xpath('//*[@id="wallpaper"]')
            print(img.get_attribute('src'))
            self.download(img.get_attribute('src'))
        except TimeoutException:
            traceback.print_exc()
            pass
        except NoSuchElementException:
            traceback.print_exc()
            pass

    def __del__(self):
        self.quit()

    def quit(self):
        self.driver.quit()

    def close(self):
        self.driver.close()


if __name__ == "__main__":
    # http://alpha.wallhaven.cc/latest
    # http://alpha.wallhaven.cc/toplist
    # http://alpha.wallhaven.cc/random

    wallPaper = WallPaper('http://alpha.wallhaven.cc/random')
    while True:
        try:
            wallPaper.run()
            print('set wall paper success.')
        except TimeoutException:
            traceback.print_exc()
            pass
        print('finish, ' + time.strftime('%Y-%m-%d %H:%M:%S',
                                         time.localtime(time.time())))
        time.sleep(10 * 60)

    print('finish')

总结

    其实,webdriver可以用来爬取许多东西,比如大数据收集,提取等等,图片只是其中比较基本的内容,它也可以用来执行网页当中的js脚本。