Traitor 发表于 2022-12-29 22:33

【更新版】爬取Wallpaper Abyss 高清壁纸支持全站

本帖最后由 Traitor 于 2023-1-3 03:05 编辑

# 说明

壁纸网站:https://wall.alphacoders.com/?lang=Chinese 大家有兴趣的话可以去看一下,这网站服务器是在加拿大的,有条件的兄弟们,可以使用加大拿的服务器来爬取,效果会很好。

楼主,经过了一段时间的学习,抽出时间来重写了这个爬取 Wallpaper Abyss 壁纸的工具。之前代码大家可以看 https://www.52pojie.cn/thread-1539536-1-1.html 这篇帖子,对比了一下以前的代码很乱,可读性很差。依旧没有使用多线程,我在服务器测试的速度还是很快的,如果使用多线程的话,可以能会给网站带来一些压力。

# 使用

去壁纸网站去找到直接自己想爬的类型来。

#### 链接的类型

搜索链接: https://wall.alphacoders.com/search.php?search=landscape&lang=Chinese

分类链接 :https://wall.alphacoders.com/by_sub_category.php?id=168646&name=%E9%A3%8E%E6%99%AF+%E5%A3%81%E7%BA%B8&lang=Chinese

标签链接 :https://wall.alphacoders.com/tag/mountain-wallpapers?lang=Chinese

特殊链接:https://wall.alphacoders.com/by_resolution.php?w=3840&h=2160&lang=Chinese

上面四种链接类型在网站出现的比较多,这个工具在上面四种链接类型中可以自由的下载。

话不多说直接上代码,都有注释,如果有不懂的可以提出来或者有更好方案也可以提出来,大家一起学习。

```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
import urllib.parse
from lxml import etree
import re
import os


# 自定义错误
class Error(Exception):
    def __init__(self, message):
      self.message = message


class Wallpaper:
    """
    0x0 所有分辨率
    1920x1080
    """

    def __init__(self, url, path, page, min_resolution):
      self.url = url
      self.path = path
      self.params = {
            "page": page
      }
      self.min_resolution = min_resolution
      # post请求参数
      self.data = {
            # 分页
            "view": "paged",
            # 分辨率
            "min_resolution": min_resolution,
            # 分辨率等于还是至少是 可以大于等于
            "resolution_equals": "=",
            # 排序方法
            # newest 最新上传
            # rating 最多赞数
            "sort": "newest",
      }

    # 创建文件夹
    @staticmethod
    def create_dir(path):
      if not os.path.exists(path):
            os.makedirs(path)
      else:
            return "文件夹已存在"

    # 返回图片类型的文件夹名称, 根据链接的不同类型
    def get_folder_name(self):

      # 标签链接名称获取 https://wall.alphacoders.com/tag/ahri-(league-of-legends)-wallpapers?lang=Chinese
      pattern = r"tag/([\w-]+)-(.*)\?lang=Chinese"
      match = re.search(pattern, self.url)
      if match:
            content1 = match.group(1)# 获取第一个捕获组的内容
            content2 = match.group(2)# 获取第二个捕获组的内容
            image_dir_name = content1 + content2
            return image_dir_name
      # 分类链接名称获取 https://wall.alphacoders.com/by_sub_category.php?id=169908&name=%E8%8B%B1%E9%9B%84%E8%81%94%E7%9B%9F+%E5%A3%81%E7%BA%B8&lang=Chinese
      elif not match:
            try:
                params = {}
                url_params = self.url.split("?")
                temp = url_params.split("&")
                for param in temp:
                  key = param.split("=")
                  value = param.split("=")
                  params = value
                name = params.get("name", None)
                # 获取分类名称
                if name is not None:
                  image_dir_name = urllib.parse.unquote(name.split("+"))
                  return image_dir_name
                # 获取不到名称名称,那链接中的就是这种类型 https://wall.alphacoders.com/by_resolution.php?w=3840&h=2160&lang=Chinese
                else:
                  w = params.get("w")
                  h = params.get("h")
                  image_dir_name = w + "x" + h
                  return image_dir_name
            # 获取索引名称 https://wall.alphacoders.com/search.php?search=landscape&lang=Chinese
            except AttributeError:
                pattern = r"search=([^&]+)&lang=Chinese"
                match = re.search(pattern, self.url)
                if match:
                  image_dir_name = match.group(1)
                  return image_dir_name

    # 获取每一页的所有图片页面的图片链接
    def get_image_urls(self):
      url = "https://wall.alphacoders.com"
      response = requests.post(self.url, params=self.params, data=self.data, allow_redirects=False)
      # 超出页数会重定向到最大的页面,进行判断,防止重复爬取
      if response.status_code == 200:
            html = etree.HTML(response.text)
            image_page_params = html.xpath(
                '//*[@id="page_container"]//div//div[@class="thumb-container"]//div[@class="boxgrid"]//@href')
            # 判断当前页面有没有图片
            if len(image_page_params) == 0:
                raise Error("获取不到当前页码的图片,请检查页码有否有效!")
            else:
                result = []
                for image_page_param in image_page_params:
                  image_page_url = url + image_page_param
                  response_image = requests.get(image_page_url).text
                  html = etree.HTML(response_image)
                  image_urls = html.xpath("/html/body/div/div/div/div/img//@src")
                  # 这里可以用推导式
                  for i in image_urls:
                        result.append(i)
                return len(result), result
      raise Error("获取不到当前页码的图片,请检查页码有否有效!")

    def download_image(self):
      mun = 0
      error = 0
      self.create_dir(self.path)
      images_dir_name = self.get_folder_name()
      images_mun, images_urls = self.get_image_urls()
      for image_url in images_urls:
            image_name_temp = re.search(r'https://[^/]+/[^/]+/(\d+)(\.png|\.jpg)', image_url)
            # 匹配图片页面的图片是否是这两种格式,不是则跳过
            if image_name_temp is not None:
                image_name = image_name_temp.group(1)
                # 判断图片是否重复下载
                if not os.path.exists(os.path.join(self.path, images_dir_name, image_name + ".png")):
                  self.create_dir(os.path.join(self.path, images_dir_name))
                  download = requests.get(image_url).content
                  with open(os.path.join(self.path, images_dir_name, image_name + ".png"), "wb") as f:
                        f.write(download)
                  print("图片 {} 下载完成,图片地址: {}".format(image_name, image_url))
                  mun = mun + 1
                  if mun == images_mun:
                        print("当前页面图片下载完成, 一共 {} 张图片".format(mun))
                else:
                  print("已有图片: {}, 图片地址: {}".format(image_name, image_url))
                  continue
            else:
                error = error + 1
                print("下载失败 {} 张图片".format(error))


if __name__ == '__main__':
    url = input("请输入壁纸url! \n")
    # 存放图片的文件夹
    path = "images"
    '''
    分辨率
    0x0 所有分辨率
    '''
    print("""
      常用分辨率
      1920x1080
      2560x1440
      2560x1600
      3840x2160
      5120x2880
      7680x4320
    """)
    resolution = input("请输入需要下载的分辨率! \n")
    # 200 可以修为自己想怕的最大页数,当链接所有页数大于或小于都能正常爬取链接的最大页数的图片,这里可以取一个折中的值
    for page_num in range(1, 200):
      print("正在下载第 {} 页的图片".format(page_num))
      page_one = Wallpaper(url, path, str(page_num), resolution)
      print(page_one.data)


```
### 分辨率的参数
![](https://img.hecady.com/i/2022/2022012029063ad9f631a978.png)
### 效果图
![](https://img.hecady.com/i/2022/2022012029063ada5094e99c.png)
![](https://img.hecady.com/i/2022/2022012029063ada07e669c0.png)
![](https://img.hecady.com/i/2022/2022012029063ada088afcc8.png)


程序下载 :



songxianda1990 发表于 2023-2-12 10:43

大佬,我这个是啥问题,全部是下面这些内容
正在下载第 192 页的图片
{'view': 'paged', 'min_resolution': '2560x1440', 'resolution_equals': '=', 'sort': 'newest'}
正在下载第 193 页的图片
{'view': 'paged', 'min_resolution': '2560x1440', 'resolution_equals': '=', 'sort': 'newest'}

醉乡不怕套路深 发表于 2023-3-3 12:23

Traceback (most recent call last):
File "E:\download.py", line 8, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'
z这是啥问题?

yinghuochong 发表于 2022-12-30 00:08

好东西啊,谢谢分享

QT2008 发表于 2022-12-30 00:48

jori 发表于 2022-12-30 08:01

我刚试了第四个网址,里面的图片可以直接下载

CrazyLife 发表于 2022-12-30 08:19

感谢分享,学习一下

h512h 发表于 2022-12-30 08:28

学习一下感谢

观弈山人 发表于 2022-12-30 08:51

很棒的资源站,感谢分享,学习一下!

constwm 发表于 2022-12-30 08:52

我试了下,确实可以

Wapj_Wolf 发表于 2022-12-30 09:12

谢谢分享,好好学习。

syd15533548508 发表于 2022-12-30 09:35

厉害,感谢分享
页: [1] 2 3 4 5 6
查看完整版本: 【更新版】爬取Wallpaper Abyss 高清壁纸支持全站