爬虫爬取wallpaperswide上的高清壁纸

本文需要用到的库:  BeautifulSoup  Requests  re  os  Pool

这是我第一次写博客,可能布局不够美观,思路讲述不够清晰,请见谅,废话不多说,直接整:

一,分析网页

 

        本次要爬取的网站是:http://wallpaperswide.com/ 首先,打开网页,你会看到如下界面:

爬虫爬取wallpaperswide上的高清壁纸_第1张图片

界面左边是图片的分类,中间是首页图片,打开浏览器的开发者工具,然后随便选中一个图片(鼠标右键,检查),就比如我选中了第一张图片

爬虫爬取wallpaperswide上的高清壁纸_第2张图片

可以得到如图的信息,这次我们需要的是其中的href="/shadow_of_the_tomb_raider_2018_puzzle_video_game-wallpapers.html",这个具体有什么用,我稍后再说,接下来,我们继续点击刚才那张图片(注意,当鼠标放到图片上时,图片上会出现一个向下的箭头,我们不要点他,应该点击它旁边的位置)如图:

爬虫爬取wallpaperswide上的高清壁纸_第3张图片

点击后将进入以下界面:

爬虫爬取wallpaperswide上的高清壁纸_第4张图片

图片下面那些就是可供选择的分辨率,再次鼠标右键检查,点击一个你想要的分辨率,如图:

我们又得到了一个‘href’,如果你点击它,你就会弹出下载提示,所以,我们要爬取的目标就是这个下载链接,但是如果按照之前的步骤获取链接,个人认为太麻烦,经过我对下载链接的观察,我发现了一些规律:

我们将之前获取的链接 href="/shadow_of_the_tomb_raider_2018_puzzle_video_game-wallpapers.html"与刚才的链接对比

可以发现,他们有相同的部分:shadow_of_the_tomb_raider_2018_puzzle_video_game-wallpapers,所以我大胆猜测这是这张图片的名字(不信的可以照之前的步骤看看其他图片),后面的-1920*1080就是图片的分辨率,因此我们可以得出一个有效下载链接的基本结构:

/download/+'图片名字'+‘-’+‘分辨率’+‘.jpg’,有没有觉得少了点什么?/download前面是不是应该还有东西呢?答案是有的,当你进入下载界面时,你会发现,该界面的网址在前面偷偷的自动加上了 http://wallpaper.com

于是我们就得到了完整的下载链接:

http://wallpaper.com/download/+'图片名字'+‘-’+‘分辨率’+‘.jpg’,因此,当我们在手动确定好分辨率后,只要知道图片名就可以得到下载链接了,因此我们只需要获得本文所说的第一个链接就够了。这样我们就能获取到一张图片的下载链接了.

二,具体步骤:

看完上面的分析是不是对如何爬取这个网站的图片有点头绪了,下面将用代码具体演示整个爬取流程

1.,引入需要用到的库:

import requests,re,os
from bs4 import BeautifulSoup
from multiprocessing import Pool,Process

2.为了降低程序复杂度(为了装逼)我们将整个流程封装成一个类

class wallpaper(object):

3.获取要爬取的分类的地址

爬虫爬取wallpaperswide上的高清壁纸_第5张图片

分析比较上面两个链接,可以发现不同类型网页地址差别就是把/后的单词换成主页上不同类别的名字

所以可以这样初始化类:

 

    def __init__(self,url_name,mode):
        self.__parten = '/(\S+)-wallpapers.html'
        self.__headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'}
        # self.__page = page
        if mode=='by_class':
            self.__url='http://wallpaperswide.com/'+url_name+'-desktop-wallpapers.html'
        elif mode=='latest':
            self.__url='http://wallpaperswide.com/latest_wallpapers.html'
        elif mode=='top':
            self.__url = 'http://wallpaperswide.com/top_wallpapers.html'
        self.__path = re.search('http://wallpaperswide.com/(\S+).html', self.__url)[1]

 

4.得到目标网页后,我们就要开始爬取网页上的图片了

首先解析网页,我们使用requests,BeautifulSoup

创建一个解析网页的私有函数变量:

 

def __get_html(self,src,mode):
    html=requests.get(src,headers=self.__headers)
    if mode=='content':
        return html.content
    elif mode=='soup':
        self.__soup = BeautifulSoup(html.text, 'lxml')
    else :
        return 0

函数中mode表示选择解析类型,有‘content’和‘soup’

content在后面下载图片要用到,‘soup’就是调用BeautifulSoup

5.获取图片名

我们查看网页源代码可以发现图片名称都在 class=wallpapers的ul标签下的li标签里

爬虫爬取wallpaperswide上的高清壁纸_第6张图片

我们用find_all加正则获取一页图片的名称和下载链接,并增加检查文件是否存在的功能

 

def __get_imgs(self):
    url_list=self.__soup.find_all('li',class_='wall')
    for url in url_list:
        href = re.search(self.__parten, url.find('a')['href'])
        img_name = href[1] + '.jpg'
        isExists = os.path.exists(os.path.join("D:\wallpaper\\"+self.__path,img_name))
        if isExists:
            print('文件存在')
            continue
        else:
            download_url = 'http://wallpaperswide.com/download/' + href[1] + '-1920x1080.html'
            img=self.__get_html(download_url,'content')
            print(img_name,download_url)
            with open("D:\wallpaper\\"+self.__path+'\\'+img_name, 'ab') as f:
                f.write(img)

此处正则说明:例如 href=/mac_leopard_desktop-wallpapers.html 从上面的说明可知,我们要的信息只有 mac_leopard_desktop (这是图片的名称),如何从

这串字符串获取我们要的信息呢,最方便的是正则,这里的 self.__parten='/(\S+)-wallpapers.html' 前面已经初始化(正则具体用法这里不做说明,读者自行了解),这样,我们就可以获取到该分类图片的第一页的图片了

6.获取当前分类任意页数图片

当我们翻页时,注意网址变化,可以发现,网址最后一位数字代表的就是当前页码,于是,我们只要知道当前分类一共有多少页,就可以很轻松的爬取所有页的图片了。代码如下:

 

def __download_all_page(self,start_page,end_page):
    page_number=end_page-start_page+1
    for page_number in range(start_page,page_number):
        url=self.__url+'/page/'+str(page_number)
        self.__get_html(url,'soup')
        self.__get_imgs()

到这里很多人都会发现,要是该分类的实际页数小于用户给定的页数咋办?解决这个问题,我们首先要知道该分类的总页数:

从图可以发现,网页良心的把最后一页的标号展示出来了,这替我们省去了许多麻烦,所以获取页数很简单,鼠标右键,选择检查,就能找到包含页码的标签了

爬虫爬取wallpaperswide上的高清壁纸_第7张图片

最后一页的页码在 倒数第二个a标签里

创建一个得到页数的函数:

 

def __get_pagenumber(self):
    self.__get_html(self.__url,'soup')
    self.__total_page_number=int(self.__soup.find('div',class_="pagination").find_all('a')[-2].text)

得到总页数,我们就可以在当用户给定的页数范围超过实际范围时做出相应的提示和限制了:

 

self.__get_pagenumber()
print('该类型一共'+str(self.__total_page_number)+'页')
if end_page-start_page>=self.__total_page_number:
    print('页数超出范围,将按照最大页数获取')
    end_page = self.__total_page_number+start_page

7.整合流程

为了方便保存,我们创建一个文件夹专门保存爬取的图片:

 

def __Create_folder(self):
    isExists = os.path.exists(os.path.join("D:\wallpaper",self.__path))
    if not isExists:
        os.makedirs(os.path.join("D:\wallpaper", self.__path))
        os.chdir("D:\wallpaper\\" + self.__path)
        print('创建文件夹', self.__path)
    else:
        print('文件夹已存在')

 

为了方便,我们__call__()将类变成一个可调用对象:

 

 

def __call__(self,start_page,end_page):
    if end_page=self.__total_page_number:
        print('页数超出范围,将按照最大页数获取')
        end_page = self.__total_page_number+start_page
    self.__Create_folder()
    self.__download_all_page(start_page,end_page)

8.爬取图片

到目前为止,我们爬取wallpaper的图片步骤差不多完成了。接下来就是创建实例化对象了,我们使用多进程,加快爬取速度

 

if __name__ == '__main__':
    funny=wallpaper('City','by_class') #mode: by_class :按分类; latest: 爬取最新壁纸; top :热门壁纸
               #mode==by_class  第一个参数填具体分类名
    p=Pool(3)
    p.apply_async(funny,args=(1,5,))
    p.apply_async(funny, args=(5,10,))
    p.apply_async(funny, args=(10, 15,))
    p.close()
    p.join()

9.效果:

爬虫爬取wallpaperswide上的高清壁纸_第8张图片

爬虫爬取wallpaperswide上的高清壁纸_第9张图片

附:完整代码请戳这里:戳我!!!

结束语:嘿嘿,写完啦,第一次写,文中有问题的地方欢迎斧正。(转载请注明出处)

你可能感兴趣的:(Python爬虫实战)