记忆云壁纸爬取
网址:https://zvvx.cn/one/bizhi/
前言:
加油!我们都是追梦人!
本篇文章将会基于 urllib 中的request 库进行爬取,会使用 json 进行数据的序列化操作,同时也会在最后举出两种下载方式 其中会使用到 threading 线程库。
# 导入 urllib
from urllib import request
import json
import threading
首先在浏览器中找到数据接口
然后找到接口的传参规则
url = https://zvvx.cn/one/bizhi/api.php?cid=36&start=0&count=30
cid=6 分类
start=0 开始位置
count=30 张数 实测最多200张有数据,超过200张没有数据
需求:
用户输入下载的种类,下载的张数,进行下载
第一步:获得图片分类
获取所有图片分类的 cid
class_dict = {
"4K专区": 36,
"美女模特": 6,
"爱情美图": 30,
"风景大片": 9,
"小清新": 15,
"动漫卡通": 26,
"明星风尚": 11,
"萌宠动物": 14,
"游戏壁纸": 5,
"汽车天下": 12,
"炫酷时尚": 10,
"月历壁纸": 29,
"影视剧照": 7,
"节日美图": 13,
"军事天地": 22,
"劲爆体育": 16,
"BABY秀": 18,
"文字控": 35
}
第二步:交互
输出图片分类供用户选择,并接受用户的输入
# 向屏幕输出图片分类信息
print("以下分类请选择:")
for c in class_dict:
print(c, class_dict[c])
# 用户输入参数以下载
input_cid = int(input("请输入你要下载的分类[输入数字]:"))
input_count = int(input("请输入你要下载的张数[输入数字]:"))
第三步:逻辑分析
找到用户输入的参数生成必要参数,由于一次最多获得200张数据,所以需要判断是否超过200,并且超过200的值。例如:用户输入850张,由于每次200张下载,所以我们可以下载4次每次200张的,还要下载1次50张的才能下载完成。
# 定制参数规则
if input_count > 200:
index = input_count // 200
count = input_count % 200
else:
index = 0
count = input_count
举个例子帮你们理解一下:
用户A 选择 下载 “美女模特” 种类,850张 ,根据前面的图片分类可以知道 “美女模特” 的 cid 是6
再根据上面的定制参数规则可以算出:我们需要下载 4 次200张的 还要再下载一次50张的才能够下载完成。
我们现在一共获得3个参数:
- 图片的种类 --6
- 整数下载次数–4
- 余数下载次数–50
所以我们定义两个函数:
第一个函数接收这三个参数,构造三种情况的 接口url:
"""
没有余数:
没有余数可以直接整数下载
没有整数:
没有整数直接余数下载
有整数,有余数:
有整数,有余数,先整数下载,再余数下载
"""
第二个函数接收接口url,获得每张图片的 id 和 下载地址。
第四步:定义函数
函数实现:
def get_img_url(img_cid, for_index, img_count): # 接受上面获得的三个数据
"""
判断传入参数,构建图片接口
:param img_cid: 图片种类
:param for_index: 循环次数
:param img_count: 剩余张数
:return: 返回所有图片地址 字典{图片名:图片地址}
"""
# 再函数中定义了一个函数,传入 接口url 进行访问,获得图片的 id 和 图片URL地址
def requests(img_url):
"""
根据传入的接口url进行访问
:param img_url: 图片接口url
:return: None
"""
try:
# 访问数据
response = request.urlopen(url=img_url)
# 转换到 json
response = json.loads(response.read().decode("utf-8"))["data"]
# 循环获得图片 id 和图片地址,图片 id 用于图片名字
for resp in response:
mid_url = resp["url_mid"]
# 将图片 id 格式化成保存路径,我这里保存在项目目录下的 img 文件夹中(要自行创建)
url_path = "./img/" + resp["id"] + ".jpg"
return_list.append((url_path, mid_url))
except Exception as e:
print(f"{img_url} 发生访问错误:{e}")
# 声明一个变量,用于存储 图片的 id 和 图片 url 地址 ---格式:[{图片名:url}]
return_list = []
# 逻辑判断,构建图片接口
if img_count == 0:
# 没有余数,200的倍数
for i in range(for_index):
url = f"https://zvvx.cn/one/bizhi/api.php?cid={img_cid}&start={i * 200 + 1}&count=200"
requests(url)
elif for_index == 0:
# 没有整数,只有余数
url = f"https://zvvx.cn/one/bizhi/api.php?cid={img_cid}&start=0&count={img_count}"
requests(url)
elif img_count > 0:
# 有余数,先访问整数
for i in range(for_index):
url = f"https://zvvx.cn/one/bizhi/api.php?cid={img_cid}&start={i * 200 + 1}&count=200"
requests(url)
# 再访问余数
url = f"https://zvvx.cn/one/bizhi/api.php?cid={img_cid}&start={for_index * 200 +1}&count={img_count}"
requests(url)
# 返回所有图片地址
return return_list
这样我们就获得了用户输入的图片的所有张数信息,并将之存在列表中,以返回值的形式返回。
# 传入参数获得图片名称和地址
img_list = get_img_url(input_cid, index, count)
第五步:下载图片到本地
有了数据以后,我们就可以将图片下载到本地了
定义一个下载函数,接收 图片路径(根据图片id格式化获得,上述函数中有提到)和下载地址(url):
def download(file_path, url):
"""
下载图片到本地
:param file_path: 图片路径
:param url: 图片地址
:return: None
"""
try:
request.urlretrieve(url, file_path)
except Exception as e:
print(f"{file_path, url} 发生下载错误:{e}")
通过循环获得的图片列表,提取图片的路径和url 进行下载,两种下载方式:
- 第一种,直接循环调用函数进行下载
# 传入参数获得图片名称和地址
img_list = get_img_url(input_cid, index, count)
for img in img_list:
download(img[0], img[1])
# 速度可能有点慢,尤其是大量下载的时候
- 第二种,使用 threading 模块 进行下载
# 传入参数获得图片名称和地址
img_list = get_img_url(input_cid, index, count)
# 声明线程列表
thread_list = []
# 构造线程
for img in img_list:
thread_list.append(threading.Thread(target=download, args=(img[0], img[1])))
# 循环启动线程
for t in thread_list:
t.start()
# 相对来说会快一点
这样,我们就完成了壁纸的下载。
完整代码
# code = "utf-8"
from urllib import request
import json
import threading
"""
接口url: https://zvvx.cn/one/bizhi/api.php?cid=36&start=0&count=30
提取接口规则
cid=6 分类
start=0 开始位置
count=30 获取张数 实测最多200张有数据,超过200张没有数据
"""
def get_img_url(img_cid, for_index, img_count):
"""
判断传入参数,构建图片接口
:param img_cid: 图片种类
:param for_index: 循环次数
:param img_count: 剩余张数
:return: 返回所有图片地址 字典{图片名:图片地址}
"""
def requests(img_url):
"""
获取图片名称和下载地址
:param img_url: 图片接口地址
:return: None
"""
try:
# 访问数据
response = request.urlopen(url=img_url)
# 转换到 json
response = json.loads(response.read().decode("utf-8"))["data"]
# 循环获得图片 id 和图片地址,图片 id 用于图片名字
for resp in response:
mid_url = resp["url_mid"]
url_path = "./img/" + resp["id"] + ".jpg"
return_list.append((url_path, mid_url))
except Exception as e:
print(f"{img_url} 发生访问错误:{e}")
# 声明返回值
return_list = []
# 逻辑判断,构建图片接口
if img_count == 0:
# 没有余数,200的倍数
for i in range(for_index):
url = f"https://zvvx.cn/one/bizhi/api.php?cid={img_cid}&start={i * 200 + 1}&count=200"
requests(url)
elif for_index == 0:
# 没有整数,只有余数
url = f"https://zvvx.cn/one/bizhi/api.php?cid={img_cid}&start=0&count={img_count}"
requests(url)
elif img_count > 0:
# 有余数,先访问整数
for i in range(for_index):
url = f"https://zvvx.cn/one/bizhi/api.php?cid={img_cid}&start={i * 200 + 1}&count=200"
requests(url)
# 再访问余数
url = f"https://zvvx.cn/one/bizhi/api.php?cid={img_cid}&start={for_index * 200 +1}&count={img_count}"
requests(url)
# 返回所有图片地址
return return_list
def download(file_path, url):
"""
下载图片到本地
:param file_path: 图片路径
:param url: 图片地址
:return: None
"""
try:
request.urlretrieve(url, file_path)
except Exception as e:
print(f"{file_path, url} 发生下载错误:{e}")
if __name__ == '__main__':
# 分类列表
class_dict = {
"4K专区": 36,
"美女模特": 6,
"爱情美图": 30,
"风景大片": 9,
"小清新": 15,
"动漫卡通": 26,
"明星风尚": 11,
"萌宠动物": 14,
"游戏壁纸": 5,
"汽车天下": 12,
"炫酷时尚": 10,
"月历壁纸": 29,
"影视剧照": 7,
"节日美图": 13,
"军事天地": 22,
"劲爆体育": 16,
"BABY秀": 18,
"文字控": 35
}
# 向屏幕输出图片分类信息
print("以下分类请选择:")
for c in class_dict:
print(c, class_dict[c])
# 用户输入参数以下载
input_cid = int(input("请输入你要下载的分类[输入数字]:"))
input_count = int(input("请输入你要下载的张数[输入数字]:"))
# 定制参数规则
if input_count > 200:
index = input_count // 200
count = input_count % 200
else:
index = 0
count = input_count
# 传入参数获得图片名称和地址
img_list = get_img_url(input_cid, index, count)
# 声明线程列表
thread_list = []
# 构造线程
for img in img_list:
thread_list.append(threading.Thread(target=download, args=(img[0], img[1])))
# 循环启动线程
for t in thread_list:
t.start()
结果展示:
该文章仅供学习和交流。