P站每日排行榜爬虫以及邮件发送通知2

P站每日排行榜爬虫以及邮件发送通知2

  • 3.子图下载
    • 3.1子图接口分析
    • 3.2代码实现
  • 4.画师目录创建以及重复下载判断
    • 4.1重复下载跳过
    • 4.2画师目录创建

P站每日排行榜爬虫以及邮件发送通知1

3.子图下载

上篇的代码已经可以实现爬取主图的任务了,但是画师经常会上传不止一张图片,之前的代码就不能实现这一功能

3.1子图接口分析

我们找一个多张图片的作品抓取接口
P站每日排行榜爬虫以及邮件发送通知2_第1张图片
发现子图的地址只是替换了 p0p1 ,后面的依次替换 px

3.2代码实现

def down_z_picture(data):
    p = 1
    while True:
        url = data['url'].replace("p0", f"p{p}")
        p_name = url.split("/")[-1].replace("_master1200", "")  # 获得图片的名称
        # 开始下载
        img = s.get(url, headers={"referer": f"https://www.pixiv.net/artworks/{data['p_id']}"})
        if img.status_code == 404:
            break
        with open(p_name, 'wb') as f:
            # 保存图片
            f.write(img.content)
        p += 1

注意:
1. data是主图下载后传递过来的
2. 在调用这个方法前需要判断,下载地址里面是否有p0存在,有些图片的地址没有p0,会导致程序无限循环在子图下载中
3. 通过判断状态码是404说明不存在此图片,来控制退出循环

4.画师目录创建以及重复下载判断

经过前面的代码,下载图片的功能已经完成,但是存在新的问题
第一是如果已经下载过再次运行又会下载一次,非常浪费时间
第二是图片没有进行分类,后面处理起来也比较麻烦,还有就是后面添加黑名单不方便

4.1重复下载跳过

用pathlib下的Path(file_path).exists()来判断是否已经下载过

from pathlib import Path

# 判断文件或文件夹是否存在
def judge_file(file_path):
    return Path(file_path).exists()

注意:
1. file_path的路径中使用 \\ 来代表 \ 更加稳妥

4.2画师目录创建

画师的目录名称格式是 画师昵称_ID=ID值
但是画师的昵称会存在一些字符是不能创建目录的我们需要删除这些字符

del_li = [' ', '/', '|', '\t', '"', ':', '*', '\\', '<', '>', '?']


# 删除文本内容
def del_text(text):
    for i in self.del_li:
        text = text.replace(i, '')
    return text

接下来是创建目录

from os import system

# 只返回有无错误
def my_system(cmd):
    r = system(cmd)
    if r == 0:
        return True
    else:
        return False

def create_dir(data):
	u_name = del_text(data["u_name"])
	dir_name = f"{u_name}_ID={data['id']}"
	# 创建前判断是否存在
	if not judge_file(dir_name):
		my_system(f'mkdir "{dir_name}"')
	return dir_name

这样目录创建就完成了,最后调整一下之前的代码
因为方法非常多所以代码调整的比较大,前面的代码主要是提供思路
最后总结的代码

import requests
from os import system
from pathlib import Path


# 用类来进行封装
class pixiv_down:

    # 初始化一些参数
    def __init__(self):
        self.s = requests.session()  # p站爬取只能用会话才能获得返回数据
        self.s.keep_alive = False  # 设置保持连接为否
        self.native_data = []  # 存放原始数据
        self.del_li = [' ', '/', '|', '\t', '"', ':', '*', '\\', '<', '>', '?']  # windows目录删除的字符

    # 主方法
    def main_fanc(self):
        self.__get_native_data()
        self.__down_m_picture()

    # 获得原始数据,方法名前加__为私有化方法
    def __get_native_data(self):
        url = "https://www.pixiv.net/ranking.php?mode=daily&p=%d&format=json"  # 排行URL
        header = {"referer": "https://www.pixiv.net/ranking.php?mode=daily"}  # 头部跳转信息 注:应对P站防盗链,headers只需要加referer即可获得返回数据
        # 循环一共有500排行, 每页50, 一共10页
        for p in range(1, 11):
            print(f"开始处理排行第{p}页的数据")  # 输出调试信息
            # 发送请求
            r = self.s.get(url % p, headers=header, timeout=30)  # timeout设置超时30秒
            r = r.json()['contents']  # 获得排行原始数据
            # 遍历原始数据
            for i in r:
                self.native_data.append({"p_id": i["illust_id"],  # 图片ID
                                         "url": i["url"].replace('/c/240x480', ''),  # 图片地址还原大图地址
                                         "u_id": i["user_id"],  # 画师ID
                                         "u_name": self.__del_text(i["user_name"]),  # 画师昵称删除不符合的字符
                                         "header": {"referer": f"https://www.pixiv.net/artworks/{i['illust_id']}"},})  # 跳转信息
            print("排行原始数据处理完成")

    # 下载主图
    def __down_m_picture(self):
        # 遍历数据
        for data in self.native_data:
            dir_name = f'{data["u_name"]}_ID={data["u_id"]}'  # 目录名称
            self.__create_dir(dir_name)  # 创建画师目录
            p_name = self.__get_p_name(data['url'])  # 获得图片的名称
            # 开始下载
            img = self.s.get(data['url'], headers=data['header'])
            with open(f'{dir_name}/{p_name}', 'wb') as f:
                # 保存图片
                f.write(img.content)
                print(f'{p_name}保存成功')
            if "p0" in data['url']:  # 判断有p0,下载子图
                self.__down_z_picture(data, dir_name)

    # 下载子图
    def __down_z_picture(self, data, dir_name):
        p = 1
        while True:
            url = data['url'].replace("p0", f"p{p}")  # 替换p0
            p_name = url.split("/")[-1].replace("_master1200", "")  # 获得图片的名称
            # 开始下载
            img = self.s.get(url, headers=data['header'])
            if img.status_code == 404:  # 404代码无图片了
                break  # 中断循环
            with open(f'{dir_name}/{p_name}', 'wb') as f:
                # 保存图片
                f.write(img.content)
                print(f'{p_name}保存成功')
            p += 1

    # 删除文本内容
    def __del_text(self, text):
        for i in self.del_li:
            text = text.replace(i, '')
        return text

    # 判断文件或文件夹是否存在
    def __judge_file(self, file_path):
        return Path(file_path).exists()

    # 创建画师目录
    def __create_dir(self, file_path):
        if not self.__judge_file(file_path):  # 创建前判断不存在
            if self.__system(f'mkdir "{file_path}"'):
                print(f"{file_path} 创建成功")

    # 只返回有无错误
    def __system(self, cmd):
        r = system(cmd)
        if r == 0:
            return True
        else:
            return False

    # 根据url获取图片名称
    def __get_p_name(self, url):
        return url.split("/")[-1].replace("_master1200", "")


if __name__ == '__main__':
    pixiv_down().main_fanc()

你可能感兴趣的:(P站每日排行榜爬虫以及邮件发送通知2)