Python抓取壁纸

拾忆
2020-07-26 / 0 评论 / 409 阅读 / 正在检测是否收录...

安装库

在开始编写代码之前需要安装几个库

  • requests 可以发送请求的库
  • beautifulsoup4 可以从HTML或XML文件中提取数据的Python库
  • lxml 支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高

下面是安装命令,依次执行即可:

pip3 install requests
pip3 install beautifulsoup4 
pip3 install lxml

首次分析

分析页面结构是必不可少的一步,只有了解到该页面如何组成才能够如何根据页面结构编写代码
我需要爬取的网站是: https://wallpapershome.com/?page=1
通过url链接可以看出参数 page是页数.那么爬取下一页的内容只需要page往上加就行.

图片1

通过上图可以看到网页显示了12张缩略图(分辨率降低的图片,用于展示),然后下面还有分页,也就是说每页显示12张缩略图,点进去之后是缩略图的详细信息,里面有各个分辨率的下载链接,看下图

图片2

那咱们的目的就是获取下载链接然后下载

这时候回到第一页(https://wallpapershome.com/?page=1)中

按F12打开控制台,找到对应的元素.

图片3 通过上图的操作找到可以定位到第一个内容的元素标签及标签的属性

图片4

从上图中可以看到你选择的这个元素是用 <p>标签包起来的,<p>下有 <a>标签,<a>标签的属性 href值就是当前内容的详细信息链接,但是它的值开头是 /,直接访问是不可以的,需要在前面加上主域名:https://wallpapershome.com,也就是说所选内容的详细信息页面链接为:https://wallpapershome.com/download-wallpapers/windows/windows-10x-microsoft-4k-22734.html,之后可以看到与所选内容标签同级的还有11个,这12个就是第一页(page=1)的内容,这12个 <p>标签都有一个爸爸,那就是 <div class="pics" id="pics-list">,找到了他们的爸爸后便可以开始编写代码了

编写代码

先编写获取详细页面链接的代码

Tips: 编写代码之前需要知道如何使用requestsBeautifulSoup,点击文字即可跳转到推荐的文章

# 发送请求库
import requests
# 从html中提取数据库
from bs4 import BeautifulSoup

# 获取详细页面链接
def getDetailUrls(domain):
    print('网站域名:' + domain)
    # 用一个数组来存储获取到的详细页面链接
    arr = []
    # 先取第一页的内容,想要更多页的内容改大range函数的值
    for i in range(2):
        # 访问页面并获取响应
        response = requests.get(domain + '?page=' + str(i))
        # 响应成功
        if response.status_code == 200:
            # 解析HTML页面
            soup = BeautifulSoup(response.content, 'lxml')
            # 找到他们的爸爸
            pics_list = soup.select("#pics-list")[0]
            # 找到带有详情页的链接
            children = pics_list.select("a[href]")
            for item in children:
                link = domain + str(item['href'])
                arr.append(link)
    return arr


if __name__ == '__main__':
    domain = 'https://wallpapershome.com'
    # 获取详细页面链接
    detailUrls = getDetailUrls(domain)
    for detailUrl in detailUrls:
        print('获取到的详细页面链接: ' + detailUrl)

代码解释

解释一下两段代码:

  • pics_list = soup.select("#pics-list")[0]

这个意思是找到整个页面中id为pics-list的元素,为什么要加[0]呢?select函数返回的是一个数组,如果有多个id为pics-list就需要循环 pics_list变量来获取带有详情页的链接,那么id在HTML是唯一的,所以只取下标0即可.

  • children = pics_list.select("a[href]")

这段代码是指找到id为pics-list的子元素中带有href属性的a标签元素,也就是这种 <a href="xxxx"></a>元素,上面就说了 select函数返回的是一个数组,所以这里不取下标0,使用循环来获取每个a标签属性href的值

运行结果

运行结果如下:

图片5

可以数数是不是获取到了12个详细页面的链接,然后点进去看看是不是与自己点进去的画面显示一致.

再次分析

获取到详细页面的链接后需要分析该页面的结构,咱们的下载链接也在该页面,分析完这次后就不用再分析了.

那么我们打开内容的详细页面链接:https://wallpapershome.com/download-wallpapers/windows/windows-10x-microsoft-4k-22734.html

第一步开始要定位到该元素,定位到该元素后展开它的子节点,看下图

图片6

从上图的黄色框框及蓝色框框中可以看出他用了两个div来展示下载链接,但是将鼠标悬浮上面后只展示了一个div的内容,我查看了其他内容的详细页面后发现都有两个,初步了解到鼠标悬浮再DownLoad按钮下展示的是 <div class="block-download__resolutions--6">的那个元素,所以这里这个元素的下载链接,当然你也可以取另外一个,主要是这个支持的分辨率多一些

编写代码

分析完后知道要怎么做了就可以再次编写代码

# 发送请求库
import requests
# 从html中提取数据库
from bs4 import BeautifulSoup


# 获取详细页面链接
def getDetailUrls(domain):
    print('网站域名:' + domain)
    # 用一个数组来存储获取到的详细页面链接
    arr = []
    # 先取第一页的内容,想要更多页的内容改大range函数的值
    for i in range(2):
        # 访问页面并获取响应
        response = requests.get(domain + '?page=' + str(i))
        # 响应成功
        if response.status_code == 200:
            # 解析HTML页面
            soup = BeautifulSoup(response.content, 'lxml')
            # 找到他们的爸爸
            pics_list = soup.select("#pics-list")[0]
            # 找到带有详情页的链接
            children = pics_list.select("a[href]")
            for item in children:
                link = domain + str(item['href'])
                arr.append(link)
    return arr


# 获取下载链接
def getDownloadUrls(domain):
    # 用一个数组来存储下载链接
    arr = []
    # 获取详细页面链接
    detailUrls = getDetailUrls(domain)
    for detailUrl in detailUrls:
        print('获取到的详细页面链接: ' + detailUrl)
        # 发送请求
        response = requests.get(detailUrl)
        # 响应成功
        if response.status_code == 200:
            # 解析HTML页面
            soup = BeautifulSoup(response.content, 'lxml')
            # 找到下载块
            block_download = soup.select(".block-download__resolutions--6")[0]
            # 找到带有详情页的链接
            children = block_download.select("a[href]")
            for item in children:
                # 获取href属性的值并添加到数组中
                arr.append(domain + str(item['href']))
    return arr


if __name__ == '__main__':
    domain = 'https://wallpapershome.com'
    downLoadUrls = getDownloadUrls(domain)
    for url in downLoadUrls:
        print('下载链接: ' + url)

代码解释

  • block_download = soup.select(".block-download__resolutions--6")[0]

这段代码是指找到 class属性值为 block-download__resolutions--6,那么为什么又要取0呢?因为我找了整个页面都没用找到第二个相同属性及值的元素

运行结果

运行结果如下(截取部分):

图片7

下载文件

下载链接都获取到了那么就可以获取文件的内容并写入到本地中

以下是main函数里面的代码:

if __name__ == '__main__':
    domain = 'https://wallpapershome.com'
    downLoadUrls = getDownloadUrls(domain)
    for url in downLoadUrls:
        print('下载链接: ' + url)
        fileName = url[url.rfind('/') + 1:]
        print('文件名为: ' + fileName)
        # 下载文件
        response = requests.get(url)
        # 响应成功
        if response.status_code == 200:
            data = response.content
            with open("c:/" + fileName, "wb") as code:
                code.write(data)

代码解释

  • fileName = url[url.rfind('/') + 1:]
    这段代码是为了截取文件名,python中字符串函数有find()函数,意思是从左边往右边查找,rfind()就是从右往左边找,那么rfind('/')这段的意思是找出该字符串中最后一个/的下标,那么+1: 是什么意思呢?这里要分开理解+1是指最后一个/的下标+1,不+1的话截取出来的字符串会带上这个/,:后面截止下标,如果不写的话就是到该字符串结尾,其实就是相当于fileName = url[url.rfind('/') + 1:len(url)]
  • data = response.content
    获取该响应的内容,如果是网页的话该属性值就是一段html代码
  • with open("c:/" + fileName, "wb") as code:

with open函数有两个参数,第一个参数是保存到本地文件的位置及文件名,第二个参数的意思是: 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

Tips: 搜索关键字:with open可以了解到更深的知识

  • code.write(data)

这段代码就是写入数据到本地文件

全部代码

# 发送请求库
import requests
# 从html中提取数据库
from bs4 import BeautifulSoup


# 获取详细页面链接
def getDetailUrls(domain):
    print('网站域名:' + domain)
    # 用一个数组来存储获取到的详细页面链接
    arr = []
    # 先取第一页的内容,想要更多页的内容改大range函数的值
    for i in range(2):
        # 访问页面并获取响应
        response = requests.get(domain + '?page=' + str(i))
        # 响应成功
        if response.status_code == 200:
            # 解析HTML页面
            soup = BeautifulSoup(response.content, 'lxml')
            # 找到他们的爸爸
            pics_list = soup.select("#pics-list")[0]
            # 找到带有详情页的链接
            children = pics_list.select("a[href]")
            for item in children:
                link = domain + str(item['href'])
                arr.append(link)
    return arr


# 获取下载链接
def getDownloadUrls(domain):
    # 用一个数组来存储下载链接
    arr = []
    # 获取详细页面链接
    detailUrls = getDetailUrls(domain)
    for detailUrl in detailUrls:
        print('获取到的详细页面链接: ' + detailUrl)
        # 发送请求
        response = requests.get(detailUrl)
        # 响应成功
        if response.status_code == 200:
            # 解析HTML页面
            soup = BeautifulSoup(response.content, 'lxml')
            # 找到下载块
            block_download = soup.select(".block-download__resolutions--6")[0]
            # 找到带有详情页的链接
            children = block_download.select("a[href]")
            for item in children:
                # 获取href属性的值并添加到数组中
                arr.append(domain + str(item['href']))
    return arr


if __name__ == '__main__':
    domain = 'https://wallpapershome.com'
    downLoadUrls = getDownloadUrls(domain)
    for url in downLoadUrls:
        print('下载链接: ' + url)
        fileName = url[url.rfind('/') + 1:]
        print('文件名为: ' + fileName)
        # 下载文件
        response = requests.get(url)
        # 响应成功
        if response.status_code == 200:
            data = response.content
            with open("c:/" + fileName, "wb") as code:
                code.write(data)
23

评论 (0)

取消